netlib.narod.ru | < Назад | Оглавление | Далее > |
Чаще всего контур визуализируют при помощи одного из методов класса Graphics:
Методы Graphics (выборочно)
void DrawPath(Pen pen, GraphicsPath path) |
void FillPath(Brush brush, GraphicsPath path) |
Метод DrawPath рисует заданным пером прямые и кривые, составляющие контур. FillPath заливает внутренние области всех замкнутых фигур, используя заданную кисть. Хотя этот метод закрывает открытые фигуры, чтобы выполнить заливку, он не вносит в контур постоянных изменений. Если в контуре есть пересекающиеся линии, то заливка внутренних областей определяется значением свойства FillPath объекта GraphicsPath. При визуализации все точки контура подвергаются любым преобразованиям, установленным для объекта Graphics.
А теперь посмотрим, как все это работает на практике. Программа Flower рисует цветок при помощи контуров и преобразования.
Flower.cs
//--------------------------------------- // Flower.cs (C) 2001 by Charles Petzold //--------------------------------------- using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; class Flower: PrintableForm { public new static void Main() { Application.Run(new Flower()); } public Flower() { Text = "Flower"; } protected override void DoPage(Graphics grfx, Color clr, int cx, int cy) { // Рисуем зеленый стебель из нижнего левого угла к центру grfx.DrawBezier(new Pen(Color.Green, 10), new Point(0, cy), new Point(0, 3 * cy / 4), new Point(cx / 4, cy / 4), new Point(cx / 2, cy / 2)); // Устанавливаем преобразование для оставшегося цветка float fScale = Math.Min(cx, cy) / 2000f; grfx.TranslateTransform(cx / 2, cy / 2); grfx.ScaleTransform(fScale, fScale); // Рисуем красные лепестки GraphicsPath path = new GraphicsPath(); path.AddBezier(new Point( 0, 0), new Point(125, 125), new Point(475, 125), new Point(600, 0)); path.AddBezier(new Point(600, 0), new Point(475, -125), new Point(125, -125), new Point( 0, 0)); for (int i = 0; i < 8; i++) { grfx.FillPath(Brushes.Red, path); grfx.DrawPath(Pens.Black, path); grfx.RotateTransform(360 / 8); } // Рисуем желтый круг в центре Rectangle rect = new Rectangle(-150, -150, 300, 300); grfx.FillEllipse(Brushes.Yellow, rect); grfx.DrawEllipse(Pens.Black, rect); } }
Исполнение метода DoPage начинается с рисования изображающей стебель цветка кривой Безье, которая начинается из левого нижнего угла и заканчивается в центре клиентской области (или страницы принтера). Далее программа задает глобальное преобразование, чтобы создать изотропную область для рисования, разбитую на четыре квадранта. Координаты этой области меняются от –1000 до 1000, а начало координат расположено в центре области.
Далее программа должна нарисовать несколько лепестков, и здесь в дело вступает контур. Если бы лепестки были эллиптическими, я просто вызвал бы метод FillEllipse. Но форма лепестка точнее определяется парой кривых Безье, а для заливки полученной фигуры нужен контур. Создав контур, программа восемь раз вызывает методы FillPath и DrawPath. Каждый раз после их вызова RotateTransform изменяет глобальное преобразование объекта Graphics, в результате лепестки располагаются по кругу вокруг центра цветка. Метод DoPage завершается рисованием желтого круга в центре клиентской области.
Уверен, вы помните программу Scribble из главы 8. Тогда я показывал, как сохранить все нарисованные пользователем линии при помощи класса ArrayList. Этот объект напоминает массив, способный динамически изменять свой размер. На самом деле применение объекта ArrayList весьма напоминает сохранение координат в контуре. Замена ArrayList объектом GraphicsPath позволяет существенно упростить программу, которая в этом случае становится даже проще, чем версия из главы 11 (ScribbleWithBitmap), сохраняющая рисунок при помощи скрытого изображения.
ScribbleWithPath.cs
//------------------------------------------------- // ScribbleWithPath.cs (C) 2001 by Charles Petzold //------------------------------------------------- using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; class ScribbleWithPath: Form { GraphicsPath path; bool bTracking; Point ptLast; public static void Main() { Application.Run(new ScribbleWithPath()); } public ScribbleWithPath() { Text = "Scribble with Path"; BackColor = SystemColors.Window; ForeColor = SystemColors.WindowText; // Создаем контур path = new GraphicsPath(); } protected override void OnMouseDown(MouseEventArgs mea) { if (mea.Button != MouseButtons.Left) return; ptLast = new Point(mea.X, mea.Y); bTracking = true; // Начало фигуры path.StartFigure(); } protected override void OnMouseMove(MouseEventArgs mea) { if (!bTracking) return; Point ptNew = new Point(mea.X, mea.Y); Graphics grfx = CreateGraphics(); grfx.DrawLine(new Pen(ForeColor), ptLast, ptNew); grfx.Dispose(); // Добавляем линию path.AddLine(ptLast, ptNew); ptLast = ptNew; } protected override void OnMouseUp(MouseEventArgs mea) { bTracking = false; } protected override void OnPaint(PaintEventArgs pea) { // Рисуем контур pea.Graphics.DrawPath(new Pen(ForeColor), path); } }
Помимо дополнительной инструкции using, для превращения версии программы Scribble, не сохраняющей пользовательские рисунки, в ScribbleWithPath, нужно определить контур как переменную-поле и добавить всего 4 инструкции, прокомментированные в тексте программы.
Контур создается в конструкторе формы. Когда курсор находится над клиентской областью формы, нажатие любой кнопки мыши вызывает метод StartFigure, начинающий новую фигуру. Вызов AddLine во время исполнения метода OnMouseMove добавляет к контуру новую линию, а метод OnPaint просто вызывает DrawPath.
netlib.narod.ru | < Назад | Оглавление | Далее > |