{
Obs obs= (Obs) ob;
System.out.print("object num= "+ obs.num);
System.out.println(" n= "+ obs.n);
}
};
class BallsCj1
{
public static void main ()
{
Balls pBalls= new Balls ( ); // Создать объекты класса Balls
System.out.println("objects are working");
// Объекты функционируют 20 мс
try
{
Thread.sleep (20);
}
catch(InterruptedException iE){}
pBalls.Suspend ( ); // Приостановить объекты
System.out.println("objects are suspend and are resumed");
pBalls.Resume ( ); // Возобновить выполнение объектов
// Объекты функционируют 20 мс
try
{
Thread.sleep (20);
}
catch(InterruptedException iE){}
pBalls.Suspend ( ); // Приостановить объекты
}
}
/*
Результат:
objects are working
object 1 n= 0
object num= 1 n= 0
object 2 n= 0
object num= 2 n= 0
object 1 n= 1
object num= 1 n= 1
object 2 n= 1
object num= 2 n= 1
objects are suspend and are resumed
object 1 n= 2
object num= 1 n= 2
object 2 n= 2
object num= 2 n= 2
object 1 n= 3
object num= 1 n= 3
object 2 n= 3
object num= 2 n= 3
*/
5.3.4. Этап 4. Разработка прикладного окна
Наступил этап разработки, когда появится прикладное окно приложения с перемещающимися шарами.
Наследовав класс Form или Frame, класс Balls существенно расширит свою функциональность. Теперь можно создать прикладное окно (основную форму) и дочернее окно (дочернюю форму). Но дочернее окно будет создано потом в классе User, порождённым из класса Balls. Диаграмма классов и реализация этого этапа представлены на рис. 5.3.4.1 и в примерах 5.3.4.1 и 5.3.4.2.
Рис. 5.3.4.1. Диаграмма классов Balls–приложения четвёртого этапа
Пример 5.3.4.1. Реализация четвёртого этапа разработки Balls–приложения на языке C#.
////////////////////
// C# File Balls4Cs.cs
// Файл BallsCc4.cs полностью включает файл BallsCs3.cs, дополнив его
// данными класса Ball и класса Balls, необходимыми для рисования шаров.
// В результате наследования класса Balls из базового класса Form появилось
// прикладное окно, свойства которого установлены в конструкторе класса
// Balls. Переопределена функция OnPaint перерисовки. Функция HandlerEv,
// реагируя на событие ev из потоков, вызывает перерисовку шаров.
// Изменения файла BallsCs3.cs выделены жирным шрифтом
//
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
delegate void delEv ( );
class Ball // Класс обычного объекта
{
public event delEv ev;
public int x, y;
public int w, h;
public int dx, dy;
. . .
public Ball (int Num , int X, int Y, int Dx, int Dy) // Конструктор
{
num= Num; life= false; run= false;
w= 100; h= 100; x= X; y= Y; dx= Dx; dy= Dy;
Start();
}
//---------------
. . .
void BallFunc ( ) // Выполнить поток
{
int n= 0;
while ((life)) //&&(n<=2))
{
Console.Write ("Объект {0}", num.ToString ( ));
Console.WriteLine (" n= {0}", n.ToString ( ));
n++;
x += dx; y += dy;
if (x>w || x<0) dx= -dx;
if (y>h || y<0) dy= -dy;
if (ev != null)
{
Console.WriteLine (" Event");
ev ( );
}
Thread.Sleep (100);
}
Console.Write ("Объект {0}", num.ToString ( ));
Console.WriteLine (" завершён");
}
}
//-------------------------------------
class Balls : Form
{
Ball [] pBall;
Color col;
public Balls ( )
{
col= System.Drawing.Color.FromArgb (0, 0, 255);
pBall= new Ball [2];
for (int i= 0; i < 2; i++)
{
pBall[i]=new Ball (i, i*3+10,
1*3+15, i*3+5, i*3+5);
pBall[i].ev+= new delEv(HandlerEv );
}
Text= "Balls";
Start ( );
}
. . .
protected override void OnPaint (PaintEventArgs arg)
{
base.OnPaint (arg);
for (int i= 0; i < 2; i++)
{
arg .Graphics.DrawEllipse
(new Pen (col), pBall[i].x,
pBall[i].y, 20, 20);
pBall[i].w= Width;
pBall[i].h= Height;
}
}
void HandlerEv ( )
{
Console.WriteLine (" HandlerEv");
Invalidate ( );
}
//-------------------------
static void Main()
{
Application.Run(new Balls ( ));
}
}
/*
Результат:
Появилось прикладное окно с двумя нарисованными шарами.
Объект 0 n= 0
Event
HandlerEv
Объект 1 n= 0
Event
HandlerEv
Объект 0 n= 1
Event
HandlerEv
Объект 1 n= 1
Event
HandlerEv
Объект 0 завершился
Объект 1 завершился
*/
Рис. 5.3.4.1. Прикладное окно с консолью Balls–приложения 4 этапа
Пример 5.3.4.2. Реализация четвёртого этапа разработки Balls–приложения на языке Java.
package BallsCj4;
////////////////////
//C# File BallsCj4
import java.util.*;
import java.awt.*;
class Obs
{
public int num, n;
public Obs (int num, int n)
{this.num= num; this.n= n;}
int getNumber(){return num;}
int getN(){return n;}
}
class Ball extends Observable implements Runnable // Класс обычного объекта
{
int num;
Thread thread;
boolean run;
boolean waiting= false;
boolean life;
public int x, y;
public int w, h;
public int dx, dy;
public Ball (int Num , int X, int Y, int Dx, int Dy)// Конструктор
{
num= Num; life= false; run= false;
w= 100; h= 100; x= X; y= Y; dx= Dx; dy= Dy;
Start ( );
}
public void Start ( ) // Стартовать
{
if (!run)
{
run= true;
life= true;
thread= new Thread (this);
thread.start ( );
}
}
//---------------
synchronized public void Suspend ( ) // Приостановить
{
if (run)
{
run= false;
waiting=true;
}
}
//---------------
synchronized public void Resume ( ) // Возобновить
{
if (!run)
{
run= true;
waiting=false;
notify();
}
}
//---------------
public void run ( ) // Выполнить поток
{
int n= 0;
while ((life)) //&&(n<=2))
{
System.out.print("object "+num);
System.out.println(" n= "+n);
n++;
x += dx; y += dy;
if (x>w || x<0) dx= -dx;
if (y>h || y<0) dy= -dy;
// Уведомить
setChanged();
notifyObservers(new Obs(num, n));
try
{
Thread.sleep (10);
synchronized(this)
{
if(waiting)
wait();
}
}
catch(InterruptedException iE){}
}
System.out.print("object "+num);
System.out.println(" finished ");
}
}
//-------------------------------------
class Balls extends Frame implements Observer // Класс объектов
{
Ball [] pBall;
Color col;
public Balls ( )
{
col= Color.red;
pBall= new Ball [2];
for (int i= 0; i < 2; i++)
{
pBall[i]=new Ball (i, i*3+10,
1*3+15, i*3+5, i*3+5);
pBall[i].addObserver(this);
}
this.setTitle("Balls");
this.setSize(400, 300);
this.show();
Start ( );
}
//---------------
public void Start ( ) // Стартовать
{
for(int i=0; i < 2; i++)
{
pBall[i]. Start ( );
}
}
//---------------
public void Suspend ( ) // Возобновить
{
for (int i=0; i < 2; i++)
pBall[i].Suspend ( );
}
//---------------
public void Resume ( ) // Приостановить
{
for (int i= 0; i < 2; i++)
pBall[i].Resume ( );
}
public void update (Observable r, Object ob) // Обработчик события ev
{
Obs obs= (Obs) ob;
System.out.print("object num= "+ obs.num);
System.out.println(" n= "+ obs.n);
repaint();
}
public void paint (Graphics g)
{
super.paint (g);
g.setColor(col);
for (int i= 0; i < 2; i++)
{
g.drawOval(pBall[i].x, pBall[i].y, 20, 20);
pBall[i].w= this.getSize().width;
pBall[i].h= this.getSize().height;
}
}
}
class BallsCj1
{
public static void main ()
{
Balls pBalls= new Balls ( ); // Создать объекты класса Balls
pBalls.Start(); //!!
System.out.println("objects are working");
// Объекты функционируют 20 мс
try
{
Thread.sleep (20);
}
catch(InterruptedException iE){}
pBalls.Suspend ( ); // Приостановить объекты
System.out.println("objects are suspend and are resumed");
pBalls.Resume ( ); // Возобновить выполнение объектов
// Объекты функционируют 20 мс
try
{
Thread.sleep (20);
}
catch(InterruptedException iE){}
//pBalls.Suspend ( ); // Приостановить объекты //!!
}
}
/*
Результат:
Появилось прикладное окно с двумя нарисованными шарами.
objects are working
object 1 n= 0
object num= 1 n= 0
object 2 n= 0
object num= 2 n= 0
object 1 n= 1
object num= 1 n= 1
object 2 n= 1
object num= 2 n= 1
objects are suspend and are resumed
object 1 n= 2
object num= 1 n= 2
object 2 n= 2
object num= 2 n= 2
object 1 n= 3
object num= 1 n= 3
object 2 n= 3
object num= 2 n= 3
*/
5.3.5. Этап 5. Разработка дочернего окна с кнопкой
Создадим дочернее окно с кнопкой, управляющей перемещением шаров в области клиента прикладного окна. Диаграмма классов и реализация пятого этапа представлены на рис. 5.3.5.1 и в примере 5.3.5.1.
Рис 5.3.5.1. Диаграмма классов Balls–приложения пятого этапа
Пример 5.3.5.1. Реализация пятого этапа разработки Balls–приложения на языке C#.
////////////////////
// C# File BallsCs5.cs
// Файл BallsCs5.cs полностью включает файл BallsCs4.cs, дополнив его
// новым классом User, порождённым из класса Balls. Класс User содержит
// управляющий элемент–кнопку, нажатие на которую приостанавливает
// или возобновляет перемещение шаров.
// Изменения файла BallsCs4.cs выделены жирным шрифтом
. . .
//-------------------------------------
class Ball // Класс обычного объекта
{ . . .
void BallFunc ( )
{
int n= 0;
while (life)
{
. . .
}
Console.Write ("Объект {0}", num.ToString ( ));
Console.WriteLine (" завершён");
}
} . . .
//-------------------------------------
class User : Balls // Класс пользователя шаров
{
private bool run;
Form pChildForm;
Button pBut;
public User ( )
{
run= true;
//---------------
pBut= new Button();
pBut.Location = new Point (32, 24);
pBut.Name = "pBut";
pBut.Size = new System.Drawing.Size (32, 24);
pBut.Text = "OK";
pBut.Click += new EventHandler (OnBut);
ClientSize = new System.Drawing.Size (200, 150);
//---------------
pChildForm= new Form ( );
pChildForm.Location= new Point (250, 10);
pChildForm.Size= new Size (250, 250);
pChildForm.Text= "User";
pChildForm.Show ( );
pChildForm.Controls.Add (pBut);
pChildForm.ClientSize = new System.Drawing.Size (200, 62);
}
//---------------
void OnBut (object obj, EventArgs arg) // Обработчик кнопки
{
Console.WriteLine ("OkMouse");
if (run)
{
run= false;
Suspend ( );
}
else
if (!run)
{
run= true;
Resume ( );
}
}
//-------------------------
static void Main ( )
{
Application.Run (new User ( ));
}
}
/*
Результат:
Появились прикладное окно с перемещающимися шарами и дочернее окно
с кнопкой. При нажатии на кнопку можно приостанавливать или возобновлять
движение шаров.
*/
Рис. 5.3.5.1. Две формы с консолью Balls–приложения 5 этапа
Пример 5.3.5.2. Реализация пятого этапа разработки Balls–приложения на языке Java.