Изучение механизма потоков для смены графических изображений в C#

Цель занятия

Изучить возможности механизма потоков на примере смены графических изображений. Дополнительно см. разд. "Потоки в Java" главы 2.

Краткие теоретические сведения

Механизм потоков позволяет параллельно с основным потоком управления в программе выполнять один или несколько других потоков управления. Этот механизм нам уже знаком по курсу Java. Нам надлежит научиться порождать поток и выполнять задержку его выполнения на некоторое фиксированное время.

Каждый раз, когда эта задержка иссякает и поток активизируется, происходит смена картинки. В результате выполняется анимация изображения.

Нам потребуется также овладеть основами вывода графики в C#. С этого, пожалуй, проще всего и начать. Следующее приложение создается на основе формы Windows Application и текст его мы помещаем полностью (листинг 4.7).

Листинг 4.7. Еще одно приложение для рисования на форме

using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; namespace lesson3graphics

/// <summary>

/// Summary description for Forml.

/// </summa ry>

public class My : System.Windows.Forms.Form /// <summary>

/// Required designer variable.

/ / / < / summa ry>

private System.ComponentModel.Container components = null; public My()

//

// Required for Windows Form Designer support //

InitializeComponent();

//

// TODO: Add any constructor code after InitializeComponent // call //

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose ();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code /// <summary>

/// Required method for Designer support – do not modify /// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

this.components = new System.ComponentModel.Container();

// this.Size = new System.Drawing.Size(300,300);

// this.Text = "Forml";

this.BackColor=System.Drawing.Color.Bisque;

this.ClientSize=new System.Drawing.Size(4 00,4 00);

this.Name="Lesson-Graphics";

this.Text="LESSONC#";

this.Paint+=new

System.Windows.Forms.PaintEventHandler(this.MyPaint);

#endregion /// <summary>

/// The main entry point for the application.

/ / / < / summa ry>

[STAThread] static void Main()

{

Application.Run(new My());

}

private void MyPaint(object sender,

System.Windows.Forms.PaintEventArgs

e)

{

Graphics g=e.Graphics;

Pen p= new Pen(Color.Black,10); g.DrawLine(p,25,25,300,300); p.Color=Color.Red; g.DrawEllipse(p,50,50,100,100);

}

Результат работы этого приложения показан на рис. 4.5.

Рис. 4.5. Еще один пример рисования на форме

Программа рисует овал (эллипс) и прямую линию. Этой простейшей графики нам будет достаточно. Прежде всего, мы заполнили следующий текст инициализации:

private void InitializeComponent()

{

this.components = new System.ComponentModel.Container(); //this.Size = new System.Drawing.Size(300,300);

//this.Text = "Forml";

this.BackColor=System.Drawing.Color.Bisque; this.ClientSize=new System.Drawing.Size(4 00,4 00); this.Name="Lesson-Graphics"; this.Text="LESSONC#";

this.Paint+=new System.Windows.Forms.PaintEventHandler(this.MyPaint);

}

#endregion

В тексте инициализации управляем цветом формы:

this.BackColor=System.Drawing.Color.Bisque; размером формы:

this.ClientSize=new System.Drawing.Size(400,400);

и указываем обработчик события onPaint(). Вы, вероятно, догадались, что это выполняет строка

this.Paint+=new

System.Windows.Forms.PaintEventHandler(this.MyPaint);

Запомните синтаксис этой конструкции, так как и для других событий ваши собственные обработчики указываются так же. Процедура-обработчик — MyPaint. Само имя MyPaint здесь можно изменить на любое другое. Текст этой процедуры помещен в самом приложении — найдите его. Обратите внимание на наличие аргументов, передаваемых в процедуру, — они стандартные, но нам потребуется объект-событие System. Windows . Forms . PaintEventArgs e. Этот объект предоставляет компонент Graphics, который собственно и нужен для рисования. Мы видим, как он используется:

Graphics g=e.Graphics;

Pen p= new Pen(Color.Black,10);

g.DrawLine(p,25,25,300,300); p.Color=Color.Red; g.DrawEllipse(p,50,50,100,100);

У компонента Graphics очень много других методов и свойств, но нам пока достаточно и этих. Рисование выполняется пером, как и в других языках. В заключение два новых важных замечания.

Событие OnPaint () всегда происходит при смене размеров или местоположения окна приложения. Но его можно инициировать искусственно командой invalidate().3Toii командой мы воспользуемся чуть позже.

В этой работе мы займемся мультипликацией. Нам понадобится смена рисунков. Отображение рисунка можно реализовать так:

Bitmap b= new Bitmap("Face.bmp"); g.DrawImage(b, 10, 10, 200, 2 00) ;

// Здесь g — это объект Graphics. DrawImage рисует // картинку в указанном прямоугольнике

На этом с графикой пока все. Приступаем к потокам. Опять же приведем нечто простое — консольное приложение (листинг 4.8), в котором создается и используется поток.

Листинг 4.8. Приложение с использованием потока

using System;

using System.Threading;

class Example

public static void CountUp()

for(int i=0;i<100; i++)

Console.WriteLine("Counter now is->"+ i.ToString()); Thread.Sleep(100);

}

}

public static void Main()

{

Thread t2= new Thread(new ThreadStart(CountUp)); t2.Start(); t2.Join();

}

}

Здесь представлено консольное приложение с единственным классом Example. Для создания приложения с потоками нужно выполнить подключение пакета

using System.Threading;

В классе Exampie определены два метода: countup(), Main(). Поток создается в методе Main ():

Thread t2= new Thread(new ThreadStart(CountUp));

В конструкторе потока указывается, какой метод поток начнет выполнять по команде start. В нашем случае — это countup(). Заметим, что в методе countup() нет аргументов, однако в общем случае метод может содержать аргументы, в силу чего их нужно было бы указать в вызове (отмечено многоточием): new ThreadStart(CountUp(…))

Поток запускается так: t2. start (). Команда t2. Join () используется с тем, чтобы основная программа была приостановлена до завершения потока t2.

В методе countup () используется команда приостановки выполнения на заданное число миллисекунд (1 мс = 1/1000 с):

Thread.Sleep(100).

Созданный поток выполняет счет с задержкой и выводом на экран. И этого опять же достаточно. Теперь мы приведем полный текст приложения с формой, которое выводит динамически кружки синего цвета в разных местах экрана с задержкой. Рисование кружков связывается с событием on- Paint(), которое генерирует поток с помощью команды invalidate(). Вот полный текст работоспособного приложения (листинг 4.9).

Листинг 4.9. Приложение с потоком для анимации изображения

using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Threading; namespace graphandflows

/// <summary>

/// Summary description for Forml.

/// </summa ry>

public class Fora : System.Windows.Forms.Form /// <summary>

/// Required designer variable.

/ / / < / summa ry>

private System.ComponentModel.Container components = null; public Fora()

//

// Required for Windows Form Designer support //

InitializeComponent();

//

// TODO: Add any constructor code after InitializeComponent // call

//

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose ();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code /// <summary>

/// Required method for Designer support – do not modify /// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

this.components = new System.ComponentModel.Container(); this.Size = new System.Drawing.Size(400,400); this.Text = "FORA";

this.BackColor=System.Drawing.Color.Bisque; this.Paint+=new

System.Windows.Forms.PaintEventHandler(this.painting);

}

#endregion

public void painting(object sender,

System.Windows.Forms.PaintEventArgs e)

int i=0;

Graphics g=e.Graphics;

Pen p =new Pen(Color.Blue,5);

Random r=new Random(); i=r.Next(100);

g.DrawEllipse(p,10+r.Next(300),10+r.Next(200),i,i)

}

public void cycl()

{

int i=0; while(i<50)

{

this.Invalidate ();

Thread.Sleep(400); i++;

continue;

}

}

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread] static void Main()

{

Fora f=new Fora();

Thread t2= new Thread(new ThreadStart(f.cycl)); t2.Start();

Application.Run(f);

В этом приложении поток реализует метод cyci (). В отличие от Java для потока нет предопределенного метода run (). Перерисовка формы происходит каждые 400 мс:

this.Invalidate() ;

Thread.Sleep(400); i++;

continue;

Нет необходимости объяснять этот текст более подробно, поскольку он очень прост, но следует обратить внимание на метод Main() и способ генерации потока в нем, а именно: поток запускается до запуска основной программы в строке

Application.Run(f) .

Кроме того, процедура запуска потока указана как f.cyci, а не просто cyci(). Здесь действуют те же правила именования, что и в Java. Если вы пишете просто cyci(), то предполагается обращение к методу класса, а не методу порожденного объекта этого класса. Но тогда процедура cyci о должна быть объявлена в классе как static. У нас этого нет. Способ запуска потока в форме f.cyd вынуждает систему выполнения C# запустить именно метод cyci() объекта f, порожденного выше как Fora f=new Fora().

Задание

Используя знания, сообщенные вам в этом занятии, создайте приложение, демонстрирующее анимацию простых графических файлов, созданных в PaintBrush.

Источник: Герман О. B., Герман Ю. О., Программирование на Java и C# для студента. — СПб.: БХВ-Петербург, 2005. — 512 c.: ил.

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100