
- •9. Библиотека .Net Framework и библиотеки языка Java
- •9.1. Приложение
- •9.2. Классы, объекты и элементы приложения
- •9.3. Простейшие приложения
- •9.4. Сообщения Windows, события и делегаты
- •9.4.1. Обработка событий мыши на языке c#
- •9.4.3. Обработка событий мыши на языке Java с использованием предопределённого обработчика mouseDown
- •9.4.4. Связь события с несколькими объектами на языке c#
- •Ещё раз о событиях и уведомлении в языке Java
- •9.5.1. Обработка событий элементов интерфейса пользователя в языке Java
- •Обработка событий мыши на языке Java, используя интерфейс MouseListener
- •9.5.3. Обработка событий мыши на языке Java, используя классы адаптеров
- •9.5.4. Обработка событий мыши на языке Java, используя внутренние классы адаптеров и анонимные классы
- •9.5.5. Обработка события закрытия окна
- •Графика
- •9.6.1. Графические объекты
- •Прямоугольник
- •Класс Pen
- •Класс SolidBrush
- •Класс Font
- •Класс Graphics
- •9.7. Событие Paint и его обработчик
- •9.8. Управляющие элементы
- •Класс Button
- •Классы TextBox и TextField
- •Классы UserControl и Panel
- •9.9. Дочерние окна
- •9.10. Исключения
Классы UserControl и Panel
Объекты класса UserControl языка C# и объекты класса Panel языка Java своеобразны, поскольку представляют соответствующие управляющие элементы в окне в виде прямоугольных областей, каждая из которых обладает функциональностью окна. То есть в этой прямоугольной области можно выводить графическую информацию, применять свои потоки и события. Так в прикладном окне могут появиться прямоугольные области, самостоятельно функционирующие. Эти области (точнее, эти управляющие элементы) размещаются в окне так же, как и любые другие управляющие элементы – кнопки, редакторы и т.д. Обычно на базе классов UserControl и Panel создаются порождённые классы, в которых, воспользовавшись свойствами управляющего элемента, легко получаются координаты его левой верхней точки, размер элемента и другие свойства, а также многие функции базовых классов UserControl и Panel, включая функции OnPaint() или paint() и Invalidate() или repaint(). Такое необычное применение в порождённом классе свойств, установленных вне управляющего элемента, иллюстрируют программы примеров 9.8.4, 9.8.5 и 9.8.6.
C# и C++/CLI. Объектом класса UserControl представляется поле, обладающее свойствами и функциональностью окна. Объект создаётся конструктором:
UserControl ( );
При применении класса UserControl можно воспользоваться свойствами BackColor, ClientSize, Controls, Height, Location, Size, Visible, Width и другими, наследуемыми из класса Control, событиями Click, MouseDown, MouseUp и множеством других, наследуемых из того же класса Control. Также наследуются известные нам функции OnPaint() и Invalidate(), и масса других. Как видим, управляющий элемент типа UserControl может существенно обогатить интерфейс пользователя с программой.
Java. Также как и элемент типа UserControl, управляющий элемент типа Panel содержит сотни свойств и функций, наследуемых из базовых классов. Выделим, например, такие свойства, как getGraphics(), getSize(), getLocation(), и функции paint() и addMouseListener().
Сравните диаграммы классов рисунков 9.3.1.1 и 9.8.6. Сравнение показывает, что функциональность управляющего элемента типа UserControl и окна типа Form схожи. Что же касается управляющего элемента типа Panel и окна типа Frame, то здесь имеется отличие, как явствует из рисунков 9.3.1.2 и 9.8.7.
Рис. 9.8.6. Наследование базовых классов классом UserControl в C# и C++/CLI
Рис. 9.8.7. Наследование базовых классов классом Panel в Java
Пример 9.8.4. Программа с управляющим элементом типа UserControl на языке C# с рисованием в потоке.
Приложение имеет прикладное окно с элементом типа UserControl. В области клиента этого управляющего элемента рабочий поток рисует эллипсы со случайными цветами и размерами, сменяющие друг друга (см. рис.9.8.8).
Рис. 9.8.8. Прикладное окно программы примера 10.8.4
///////////////
// C#
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
// Класс управляющего элемента типа UserControl
class User: UserControl
{
Thread t; // Ссылка на поток
bool life; // Признак жизни потока
Graphics g; // Ссылка на графический объект
Random rand; // Ссылка на случайное число
// Конструктор
public User ( )
{
g= this.CreateGraphics (); // Создать граф.объект
rand= new Random (); // Создать случайное число
// Создать и запустить поток рисования
life= true; // Пусть поток живёт
t= new Thread (new ThreadStart (F)); // Создать объект
t.Start ( ); // Запустить поток
}
// Выполнить рабочий поток
private void F ( )
{
while(life)
{
// Нарисовать случайный эллипс в области упр.элемента
g.FillEllipse (new SolidBrush (Color.FromArgb (rand.Next(255),
rand.Next(255), rand.Next(255))),
rand.Next (this.Width),
rand.Next (this.Height),
rand.Next (this.Width<this.Height?this.Width:this.Height),
rand.Next (this.Width<this.Height?this.Width:this.Height));
// Поспать
Thread.Sleep (50);
}
}
}
// Класс прикладного окна
class W: Form
{
User u; // Ссылка на объект управляющего элемента
//Конструктор
public W ( )
{
u= new User( ); // Создать объект управляющего элемента
u.Location= new Point (50, 40);// Разместить,
u.Size =new Size (140, 130); // установить размер
u.BackColor=Color.Coral; // и фон управляющего элемента
Controls.Add (u); // Включить управляющий элемент в
// коллекцию
}
// Выполнить основной поток
static void Main ( )
{
Application.Run (new W());
}
}
Обсуждение.
C#.
Читатель.
Изменится ли функционирование программы, если воспользоваться функцией перерисовки OnPaint()?
Автор.
В нижеследующей программе в области клиента управляющего элемента типа UserControl рабочий поток совместно с функцией OnPaint() рисует эллипсы со случайными цветами и размерами. Поскольку при рисовании каждого эллипса область клиента управляющего элемента перерисовывается заново, в отличие от примера 9.8.4, в котором текущий эллипс рисуется на предыдущих эллипсах, в нижеследующем примере 9.8.5 каждый рисуемый эллипс сменяет предыдущий.
// Пример 9.8.5. Обсуждение. C# программа с управляющим элементом типа UserControl
// и функцией OnPaint().
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
// Класс управляющего элемента типа UserControl
class User: UserControl
{
Thread t; // Ссылка на поток
bool life; // Признак жизни потока
Graphics g; // Ссылка на графический объект
Random rand; // Ссылка на случайное число
// Конструктор
public User ( )
{
g= this.CreateGraphics (); // Создать граф.объект
rand= new Random (); // Создать случайное число
// Создать и запустить поток рисования
life= true; // Пусть поток живёт
t= new Thread (new ThreadStart(F)); //Создать объект потока
t.Start ( ); // Запустить поток
}
// Выполнить рабочий поток
private void F ( )
{
while (life)
{
// Перерисовать область клиента управляющего элемента
Invalidate ( );
// Поспать
Thread.Sleep (50);
}
}
protected override void OnPaint (PaintEventArgs e)
{
base.OnPaint (e);
// Нарисовать случайный эллипс в области упр.элемента
e.Graphics.FillEllipse (new SolidBrush(Color.FromArgb(rand.Next(255),
rand.Next (255),rand.Next(255))),
rand.Next (this.Width),
rand.Next (this.Height),
rand.Next (this.Width<this.Height?this.Width:this.Height),
rand.Next (this.Width<this.Height?this.Width:this.Height));
}
}
// Класс прикладного окна
class W: Form
{
User u; // Ссылка на объект управляющего элемента
//Конструктор
public W ( )
{
u= new User ( ); // Создать объект управляющего элемента
u.Location= new Point (50, 40); // Разместить,
u.Size =new Size (140, 130); // установить размер
u.BackColor=Color.LightGray; // и фон управляющего элемента
Controls.Add (u); // Включить управляющий элемент в
// коллекцию окна
}
// Выполнить основной поток
static void Main ( )
{
Application.Run (new W());
}
}
Пример 9.8.6. Программа с управляющим элементом типа Panel на языке Java с применением потока и функции paint()
Как и в программе примера 9.8.5 в данной программе рисование случайных эллипсов в пределах управляющего элемента типа Panel осуществляется функцией paint(), вызываемой посредством функции repaint() из потока. В области клиента управляющего элемента рисуются эллипсы со случайными координатами, размерами и цветами.
///////////////
// Java и J#
import java.awt.*;
import java.awt.event.*;
import java.util.*;
// Класс управляющего элемента типа UserControl
class User extends Panel implements Runnable
{
Thread t; // Ссылка на поток
boolean life; // Признак жизни потока
Graphics g; // Ссылка на графический объект
Random rand; // Ссылка на случайное число
// Конструктор
public User ( )
{
show();
this.setVisible (true); // Показать управляющий элемент
g= this.getGraphics (); // Создать графический объект
rand= new Random (); // Создать случайное число
// Создать и запустить поток рисования
life= true; // Пусть поток живёт
t= new Thread (this); // Создать объект потока
t.start ( ); // Запустить поток
}
// Завершить поток
public void Finish ( )
{
life= false;
try
{
t.join ( );
}
catch (InterruptedException e) { }
}
// Выполнить рабочий поток
public void run ( )
{
while (life)
{
System.out.println ("-----I'm working");
repaint ( );
// Поспать
try
{
Thread.sleep (50);
}
catch (InterruptedException e) { }
}
}
public void paint (Graphics g)
{
g.setColor (new Color (rand.nextInt(255),
rand.nextInt(255), rand.nextInt(255)));
// Нарисовать случайный эллипс в области упр.элемента
g.fillOval (
rand.nextInt (this.getSize().width),
rand.nextInt (this.getSize().height),
rand.nextInt (this.getSize().width<this.getSize().height?
this.getSize().width:this.getSize().height),
rand.nextInt (this.getSize().width<this.getSize().height?
this.getSize().width:this.getSize().height));
}
}
// Класс прикладного окна
class W extends Frame
{
User u; // Ссылка на объект управляющего элемента
//Конструктор
public W ( )
{
setLayout(null);
setSize (340, 230); // Установить размер
u= new User( ); // Создать объект управл. элемента
u.setLocation(50, 40); // Разместить,
u.setSize (140, 130); // установить размер
u.setBackground (Color.lightGray); // и фон управляющего
// элемента
add(u); // Включить управляющий элемент в
// коллекцию
// Применить внутренний анонимный класс
// для закрытия окна
this.addWindowListener (new WindowAdapter ( )
{
public void windowClosing (WindowEvent wE)
{
System.exit (0);
}
});
show();
}
// Выполнить основной поток
static public void main ( )
{
W w= new W ();
}
}