прнор. 8классGraphicsСоздание анимации (1). Графика на С#
Скачать 2.3 Mb.
|
Графика на С#На примере графики наглядно видны преимущества ООП, смысл использования классов, их методов и свойств. Добавляя в пространство имен своего проекта соответствующие библиотеки, вы получаете сразу набор инструментов, необходимых для графики. Это графические примитивы (линии, прямоугольники, эллипсы и т.п.), перо для черчения, кисть для закраски и много других полезных объектов и методов. Пространство имен System.Drawing (Рисование) обеспечивает доступ к функциональным возможностям графического интерфейса GDI+ , используя около 50 (!) классов, в том числе класс Graphics. Графические примитивы Класс GraphicsОн инкапсулирует поверхность рисования GDI+. Этот класс не наследуется. Методов в этом классе огромное количество, поэтому сначала представим их в таблице, а затем рассмотрим некоторые из них с примерами и пояснениями. Класс Graphics предоставляет методы рисования на устройстве отображения (другие термины — графический контекст, «холст»). Определимся сразу, на чем мы хотим рисовать. Далее в примерах он обозначается как объект g. Способы задания «холста»Графический объект — «холст» для рисования на форме Form1 (указатель this) можно задать, например, одним оператором: Graphics g = this.CreateGraphics(); Примечание. Заметим, что стандартным образом Graphics g = new Graphics(); создать объект-холст не удается. На этом операторе генерируется ошибка: Способы задания «холста»Еще пример задания графического контекста на визуальном компоненте PictureBox (ящик для рисования) через растровый объект класса Bitmap. В классе Form1 зададим два объекта: Graphics g; // графический объект — некий холст Bitmap buf; // буфер для Bitmap-изображения В конструктор Form1() добавим следующие операторы: buf = new Bitmap(pictureBox1.Width, pictureBox1.Height); // с размерами g = Graphics.FromImage(buf); // инициализация g Способы задания «холста»Eсли все графические операции выполняются внутри одной функции, можно использовать одну строку: Graphics g = Graphics.FromImage(new Bitmap(pictureBox1.Width, pictureBox1.Height)); После этого можно задать фон холста белым: g.Clear(Color.White); Еще один пример задания «холста» на форме через дескриптор окна: Graphics g = Graphics.FromHwnd(this.Handle); Способы задания «холста»Еще пример задания графического контекста на визуальном компоненте PictureBox (ящик для рисования) через растровый объект класса Bitmap. В классе Form1 зададим два объекта: Graphics g; // графический объект — некий холст Bitmap buf; // буфер для Bitmap-изображения В конструктор Form1() добавим следующие операторы: buf = new Bitmap(pictureBox1.Width, pictureBox1.Height); // с размерами g = Graphics.FromImage(buf); // инициализация g Способы задания «холста»Одним из самых используемых является получение ссылки на объект Graphics через объект PaintEventArgs при обработке события Paint формы или элемента управления: private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; // Далее вставляется код рисования } Методы класса Graphics
Начало системы координат находится в левом верхнем углу окна, внутренней области окна формы. Ось X в этой системе координат, принятой по умолчанию, направлена слева направо, а ось Y — сверху вниз. Координаты точки Точку возможно нарисовать в виде закрашенного квадрата с шириной стороны, равным 1 пикселу (или побольше). Эта задача выполняется при помощи метода FillRectangle: g.FillRectangle(redBrush, e.X, e.Y, 1, 1); private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Yellow); g.FillRectangle(Brushes. Red, 80, 70, 4, 4); } Метод FillRectangle вызывается для объекта g класса Graphics. В качестве первого параметра методу FillRectangle передается кисть redBrush, которую нужно использовать для рисования. Второй и третий параметры метода FillRectangle задают координаты, в которых будет нарисован квадрат. Класс PenКласс Pen определяет объект, используемый для рисования прямых линий и кривых. Этот класс не наследуется. Конструкторы класса: 1) Pen(Color) инициализирует новый экземпляр класса Pen с указанным цветом. 2) Pen(Color, Single) инициализирует новый экземпляр класса Pen с указанными свойствами Color и Width. Width – в устанавливает ширину пера Pen, в единицах объекта Graphics, используемого для рисования. Класс Pen. ПримерыPen redPen = new Pen(Color.Red); // толщина пера по умолчанию 1 пиксель Color green = Color.Green; // с использованием дополнительной переменной Pen greenPen = new Pen(green, 4.5f); Можно вводить новый объект без указания явного имени пера (пример создания динамического объекта – пера): g.DrawRectangle(new Pen(Color.Red, 3), r); например, для рисования прямоугольника r красным пером толщиной 3 пикселя, используя графический контекст («холст») g. Метод DrawLine рисует линию, соединяющую две точки с заданными координатами (метод перегружен). DrawLine(Pen, Point, Point); DrawLine(Pen, PointF, PointF); DrawLine(Pen, int, int, int, int); DrawLine(Pen, float, float, float, float); Первый параметр задает инструмент для рисования линии – перо. Остальные параметры методов DrawLine задают координаты соединяемых точек. Эти координаты могут быть заданы как объекты класса Point и PointF, а также в виде целых чисел и чисел с плавающей десятичной точкой. Рисование прямой линии Класс Brush определяет объекты, которые используются для заливки внутри графических фигур, таких как прямоугольники, эллипсы, круги, многоугольники и дорожки. Это абстрактный базовый класс, который не может быть реализован. Для создания объекта «кисть» используются классы, производные от Brush, такие как SolidBrush, TextureBrush и LinearGradientBrush, например: SolidBrush br = new SolidBrush(Color.Aqua); g.FillRectangle(br, r); // закраска прямоугольника r на «холсте» g Или без явного объявления объекта «кисть» br: g.FillRectangle(new SolidBrush(Color.Red), r); Класс Brush Рисование прямой линии private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Yellow); g.DrawLine(new Pen(Brushes.Blue, 2), 10, 20, 200, 30); } или Graphics g = e.Graphics; g.Clear(Color.Yellow); Pen myPen = new Pen(Color.Red, 2); g.DrawLine(myPen, 30, 50, 30, 150); Метод DrawRectangle позволяет рисовать прямоугольники, заданные координатой верхнего левого угла, а также шириной и высотой. В библиотеке классов .NET Frameworks имеется три перегруженных варианта этого метода: DrawRectangle(Pen, Rectangle); DrawRectangle(Pen, int, int, int, int); DrawRectangle(Pen, float, float, float, float); В качестве первого параметра этим методам передается перо класса Pen. Остальные параметры задают расположение и размеры прямоугольника. Класс Rectangle используется для описания расположения и размеров прямоугольной области. Свойства X и Y этого класса задают координаты верхнего левого угла прямоугольной области, соответственно, по горизонтальной и вертикальной оси координат. Рисование прямоугольника private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Yellow); Pen myPen = new Pen(Color.Red, 2); g.DrawRectangle(myPen, 10, 10, 200, 50); //незакрашеный прямоугольник g.FillRectangle(Brushes.Blue, 10, 70, 200, 80); //закрашеный прямоугольник } Рисование прямоугольника Метод DrawEllipse рисует эллипс, вписанный в прямоугольную область, расположение и размеры которой передаются ему в качестве параметров. Предусмотрено четыре перегруженных варианта метода DrawEllipse: DrawEllipse(Pen, Rectangle); DrawEllipse(Pen, RectangleF); DrawEllipse(Pen, int, int, int, int); DrawEllipse(Pen, float, float, float, float); Эти методы отличаются только способом, при помощи которого описывается расположение и размеры прямоугольной области, в которую вписан эллипс. Рисование эллипса Рисование эллипса private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Yellow); Pen myPen = new Pen(Color.Red, 2); g.DrawEllipse(myPen, 100, 100, 100, 100); //незакрашенный эллипс g.FillEllipse(Brushes. LightGray, 50, 50, 50, 50); //закрашенный эллипс } При помощи метода DrawArc программа может нарисовать сегмент эллипса. Сегмент задается при помощи координат прямоугольной области, в которую вписан эллипс, а также двух углов, отсчитываемых в направлении против часовой стрелки. Первый угол Angle1 задает расположение одного конца сегмента, а второй Angle2 – расположение другого конца сегмента. Рисование сегмента эллипса Предусмотрено четыре перегруженных варианта метода DrawArc: DrawArc(Pen, Rectangle, float, float); DrawArc(Pen, RectangleF, float, float); DrawArc(Pen, int, int, int, int, int, int); DrawArc(Pen, float, float, float, float, float, float); Первый параметр метода DrawArc определяет перо, с помощью которого будет нарисован сегмент. Расположение и размеры прямоугольной области передаются методу DrawArc аналогично тому, как это делается для рассмотренного выше метода DrawEllipse. Рисование сегмента эллипса private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Yellow); Pen myPen = new Pen(Color.Red, 2); g.DrawArc(myPen, 10, 10, 200, 150, 30, 270); // незамкнутый сегмент эллипса g.DrawPie(myPen, 30, 30, 100, 110, 20, 200); //незакрашеный замкнутый сегмент эллипса g.FillPie(Brushes.Green, 170, 10, 200, 150, 0, 120); // закрашеный замкнутый сегмент эллипса } Рисование сегмента эллипса Метод DrawPolygon поможет Вам в тех случаях, когда нужно нарисовать многоугольник, заданный своими вершинами. Предусмотрено два варианта этого метода: DrawPolygon(Pen, Point[]); DrawPolygon(Pen, PointF[]); В первом случае методу DrawPolygon через второй параметр передается массив точек класса Point, в котором координаты точек заданы целыми числами, а во втором – массив класса PointF, где координаты соединяемых точек задаются в виде числа с плавающей десятичной точкой. Рисование многоугольника Многоугольник DrawPolygon. В нем определили перо myPen и массив точек myPoints. private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Yellow); Pen myPen = new Pen(Color.Red, 2); Point[] myPoints = { new Point(40, 50), new Point(50, 60), new Point(60, 40), new Point(70, 60), new Point(80, 40), new Point(90, 60), new Point(120, 70), new Point(100, 90), new Point(50, 90), }; g.DrawPolygon(myPen, myPoints); g.FillRectangle(Brushes.Black, 100,75, 5, 5); } Рисование многоугольника Методы для рисования закрашенных фигур В классе Graphics определен ряд методов, предназначенных для рисования закрашенных фигур. Есть два отличия методов с префиксом Fill от одноименных методов с префиксом Draw. Прежде всего, методы с префиксом Fill рисуют закрашенные фигуры, а методы с префиксом Draw – не закрашенные. Кроме этого, в качестве первого параметра методам с префиксом Fill передается не перо класса Pen, а кисть класса Brush.
Пример рисования в С# Кораблик private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Turquoise); SolidBrush myCorp = new SolidBrush(Color.DarkMagenta); SolidBrush myTrum = new SolidBrush(Color.DarkOrchid); SolidBrush myTrub = new SolidBrush(Color.DeepPink); SolidBrush mySeа = new SolidBrush(Color.Blue); Pen myWind = new Pen(Color.Yellow, 2); g.FillRectangle(myTrub, 300, 125, 75, 75); g.FillRectangle(myTrub, 480, 125, 75, 75); g.FillPolygon(myCorp, new Point[] {new Point(100,300),new Point(700,300), new Point(700,300),new Point(600,400), new Point(600,400),new Point(200,400), new Point(200,400),new Point(100,300) }); g.FillRectangle(myTrum, 250, 200, 350, 100); int x = 50; int Radius = 50; while (x <= 800 - Radius) {g.FillPie(mySeа, 0 + x, 375, 50, 50, 0, -180); x += 50; } for (int i = 300; i <= 550; i += 50) { g.DrawEllipse(myWind, i, 240, 20, 20); } } Результат работы программы Метод узловой точкиprivate void Form1_Paint(object sender, PaintEventArgs e) { int x = 50, y = 50, a = 10; Graphics g = e.Graphics; g.Clear(Color.Yellow); Point[] raketa = { new Point(x, y), new Point(x + 3 * a, y), new Point(x + 5 * a, y + a), new Point(x + 11 * a, y + a), new Point(x + 13 * a, y + 3 * a), new Point(x + 11 * a, y + 5 * a), new Point(x + 5 * a, y + 5 * a), new Point(x + 3 * a, y + 6 * a), new Point(x, y + 6 * a), new Point(x + 2 * a,y + 4 * a), new Point(x + 2 * a, y + 2 * a), new Point(x,y), }; Point[] sled = { new Point(x - 2 * a, y + a), new Point(x + a, y + 2 * a), new Point(x + a, y + 4 * a), new Point(x - 2 * a, y + 5 * a), new Point(x - 2 * a, y + a), }; SolidBrush B1 = new SolidBrush(Color.DarkMagenta); SolidBrush B2 = new SolidBrush(Color.Red); g.FillPolygon(B1, raketa); g.FillPolygon(B2, sled); SolidBrush B3 = new SolidBrush(Color.Blue); g.FillEllipse(B3, x + 6 * a, y + 5 * a / 2, a, a); g.FillEllipse(B3, x + 8 * a, y + 5 * a / 2, a, a); g.FillEllipse(B3, x + 10 * a, y + 5 * a / 2, a, a); } 150,200, 20 350, 350 30 Элемент управления TimerTimer является компонентом для запуска действий, повторяющихся через определенный промежуток времени. События повторяются с периодичностью, указанной в миллисекундах в свойстве Interval. Установка свойства Enabled в значение true запускает таймер. Хотя он не является визуальным элементом, но его также можно перетащить с Панели Инструментов на форму: Элемент управления TimerНаиболее важные свойства и методы таймера: Свойство Enabled: при значении true указывает, что таймер будет запускаться вместе с запуском формы Свойство Interval: указывает интервал в миллисекундах, через который будет срабатывать обработчик события Tick, которое есть у таймера Метод Start(): запускает таймер Метод Stop(): останавливает таймер
Каждый тик таймера порождает событие Tick, обработчик которого обычно и создают в приложении. В этом обработчике могут изменяться какие-либо величины, и вызываться принудительная перерисовка окна. Для создания анимации весь код, рисующий что-либо на форме, должен находиться в обработчике события Paint.
Invalidate() – метод, делающий недействительной всю поверхность элемента управления и вызывающий его перерисовку. int t;int t; private void timer1_Tick(object sender, EventArgs e) { label2.Text = Convert.ToString(t++); // отсчет времени if (t % 5 == 0) button1.Left += 5; // перемещение кнопки }
int t;int t; private void timer1_Tick(object sender, EventArgs e) { label2.Text = Convert.ToString(t++); // отсчет времени if (t % 5 == 0) button1.Left += 5; // перемещение кнопки } private void button1_Click(object sender, EventArgs e) { if (timer1.Enabled == true) { timer1.Stop(); } else { timer1.Start(); } }
С помощью обработчика события нажатия кнопки можно либо остановить таймер, либо его опять запустить int x1 = 100, y1 = 100, x2 = 10, y2 = 10; private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Yellow); Pen myPen = new Pen(Color.Red, 2); g.FillEllipse(Brushes.LightGray, x1, y1, x2, y2); } int t = 0; private void timer1_Tick(object sender, EventArgs e) { t = t+1; label2.Text = t.ToString(); x2 = x2 + 1; // изменение большой полуоси эллипса а y2 = y2 + 1; // изменение малой полуоси эллипса b Invalidate(); //Принудительный вызов перерисовки Paint } private void button1_Click(object sender, EventArgs e) { if (timer1.Enabled == true) { timer1.Stop(); } else { timer1.Start(); } }
Метод узловой точки. Движение ракетыint x1 = 50, a1=10; private void Form1_Paint(object sender, PaintEventArgs e) { int x = x1, y = 50, a = a1; Graphics g = e.Graphics; g.Clear(Color.Yellow); Point[] raketa = { new Point(x, y), new Point(x + 3 * a, y), new Point(x + 5 * a, y + a), new Point(x + 11 * a, y + a), new Point(x + 13 * a, y + 3 * a), new Point(x + 11 * a, y + 5 * a), new Point(x + 5 * a, y + 5 * a), new Point(x + 3 * a, y + 6 * a), new Point(x, y + 6 * a), new Point(x + 2 * a,y + 4 * a), new Point(x + 2 * a, y + 2 * a), new Point(x,y), }; Point[] sled = { new Point(x - 2 * a, y + a), new Point(x + a, y + 2 * a), new Point(x + a, y + 4 * a), new Point(x - 2 * a, y + 5 * a), new Point(x - 2 * a, y + a), }; SolidBrush B1 = new SolidBrush(Color.DarkMagenta); SolidBrush B2 = new SolidBrush(Color.Red); g.FillPolygon(B1, raketa); g.FillPolygon(B2, sled); SolidBrush B3 = new SolidBrush(Color.Blue); g.FillEllipse(B3, x + 6 * a, y + 5 * a / 2, a, a); g.FillEllipse(B3, x + 8 * a, y + 5 * a / 2, a, a); g.FillEllipse(B3, x + 10 * a, y + 5 * a / 2, a, a); } private void button1_Click(object sender, EventArgs e) { if (timer1.Enabled == true) { timer1.Stop(); } else { timer1.Start(); } } private void timer1_Tick(object sender, EventArgs e) { x1 = x1 + 5; Invalidate(); //Принудительный вызов перерисовки Paint } |