На примере графики наглядно видны преимущества ООП, смысл использования классов, их методов и свойств. Добавляя в пространство имен своего проекта соответствующие библиотеки, вы получаете сразу набор инструментов, необходимых для графики. Это графические примитивы (линии, прямоугольники, эллипсы и т.п.), перо для черчения, кисть для закраски и много других полезных объектов и методов.
2D-графика делится, как вы знаете, на растровую и векторную. Растровое изображение — это набор цветных пикселей, заданных в прямоугольной области, хранящихся в файлах *.bmp, *.jpg, *.png и т.п. Самый простой растровый редактор — программа Paint. Векторная графика намного экономнее (по объемам памяти) растровой.
Так для рисования прямоугольника достаточно задать координаты двух точек (левого верхнего и правого нижнего углов) и цвет и толщину линии. В этом разделе в основном рассмотрим методы векторной графики.
Пространство имен System.Drawing (Рисование) обеспечивает доступ к функциональным возможностям графического интерфейса GDI+ , используя около 50 (!) классов, в том числе класс Graphics. Чуть позже мы будем использовать дополнительные пространства имен System.Drawing.Drawing2D, System.Drawing.Imaging, System.Drawing.Printing, System.Drawing.Text, расширяющие функциональные возможности библиотеки System.Drawing.
Создание приложения Рисование в Mit App Inventor 11 класс
Класс Graphics предоставляет методы рисования на устройстве отображения (другие термины — графический контекст, «холст»). Определимся сразу, на чем мы хотим рисовать. Далее в примерах он обозначается как объект g.
Способы задания «холста»
1. Графический объект — «холст» для рисования на форме Form1 (указатель this) можно задать, например, одним оператором:
Graphics g = this.CreateGraphics();
Примечание. Заметим, что стандартным образом
Graphics g = new Graphics();
создать объект-холст не удается.
На этом операторе генерируется ошибка:
Для типа «System.Drawing.Graphics» не определен конструктор.
2. Еще пример задания графического контекста на визуальном компоненте PictureBox (ящик для рисования) через растровый объект класса Bitmap. В классе Form1 зададим два объекта:
Graphics g; // графический объект — некий холст
Bitmap buf; // буфер для Bitmap-изображения
В конструктор Form1() добавим следующие операторы:
buf = new Bitmap(pictureBox1.Width, pictureBox1.Height); // с размерами
g = Graphics.FromImage(buf); // инициализация g
3. В принципе, иногда (если все графические операции выполняются внутри одной функции) эти четыре строки могут быть заменены одной строкой:
Graphics g = Graphics.FromImage(new Bitmap(pictureBox1.Width, pictureBox1.Height));
После этого можно задать фон холста белым:
g.Clear(Color.White);
4. Еще один пример задания «холста» на форме через дескриптор окна:
Graphics g = Graphics.FromHwnd(this.Handle);
Далее в примерах конкретизируются эти способы.
Объекты других классов из библиотеки System.Drawing
Такие классы, как Rectangle (прямоугольник) и Point (точка) инкапсулируют элементы GDI+. Отметим, что Point вообще то является структурой (struct) с полями x,y. Это уточнение несущественно, так как в C# структуры похожи на классы, a инициализация объекта-структуры point может выглядеть так же, как инициализация объекта-класса:
Не умеешь рисовать? Держи годный лайфхак для рисования!
Point point= new Point();
Класс Pen (перо) используется для рисования линий и кривых, а классы, производные от класса Brush (кисть) используются для закраски замкнутых контуров (см. ниже).
Класс GraphicsPath позволяет задавать последовательность соединенных линий и кривых, класс Region описывает внутреннюю часть графической формы, состоящей из многоугольников и контуров.
Класс Image – абстрактный базовый класс предоставляет функциональные возможности для производных классов Bitmap и Metafile. Bitmap используется для работы с пиксельными изображениями (см. выше пример). Metafile определяет графический метафайл, содержащий записи, описывающие последовательность графических операций, которые могут быть записаны (созданы) и воспроизведены (отображается). Этот класс не наследуется.
Класс Graphics
Он инкапсулирует поверхность рисования GDI+. Этот класс не наследуется. Методов в этом классе огромное количество, поэтому сначала представим их в таблице, а затем рассмотрим некоторые из них с примерами и пояснениями.
В третьем столбце таблицы указывается число перегрузок метода, различающихся набором параметров (используйте интеллектуальную подсказку IntelliSense для выбора нужного Вам варианта метода).
Имя метода | Описание | Число перегрузок |
Clear(Color) | Очищает всю поверхность рисования и выполняет заливку поверхности указанным цветом фона. | 1 |
CopyFromScreen(Point, Point, Size) | Выполняет передачу данных о цвете, соответствующих прямоугольной области пикселей, блоками битов с экрана на поверхность рисования объекта Graphics. | 4 |
Dispose() | Освобождает все ресурсы, используемые данным объектом Graphics. | 1 |
DrawArc(Pen, Rectangle, Single, Single) | Рисует дугу, которая является частью эллипса, заданного структурой Rectangle. | 4 |
DrawBezier(Pen, Point, Point, Point, Point) | Рисует кривую Безье, определяемую четырьмя структурами Point. | 3 |
DrawBeziers(Pen, Point[]) | Рисует несколько (N) кривых Безье, определяемых массивом из (3N+1) структур Point. | 2 |
DrawCloseCurve(Pen, Point[ ]) | Рисует замкнутый фундаментальный сплайн | 4 |
DrawEllipse(Pen, Rectangle) | Рисует эллипс | 4 |
DrawIcon(Icon, Rectangle) | Рисует значок | 2 |
DrawImage(Image image, int x, int y) | Рисует заданное изображение image, используя его фактический размер в месте с координатами (x,y) | 30 |
DrawLine(Pen, Point, Point) | Проводит линию, соединяющую две структуры Point. | 4 |
DrawLines(Pen, Point[ ]) | Рисует набор сегментов линий, которые соединяют массив структур Point. | 2 |
DrawPath(Pen, gp) | Рисует пером Pen объект GraphicsPath gp. | 1 |
DrawPie(Pen, Rectangle, Single, Single) | Рисует сектор, который определяется эллипсом, заданным структурой Rectangle и двумя радиалtьными линиями. | 4 |
DrawPolygon(Pen, Point[]) | Рисует многоугольник, определяемый массивом структур Point. | 2 |
DrawRectangle(Pen, Rectangle) | Рисует прямоугольник, определяемый структурой Rectangle. | 3 |
DrawRectangles(Pen, Rectangle[]) | Рисует набор прямоугольников, определяемых структурами Rectangle. | 2 |
DrawString(String, Font, Brush, PointF) | Создает указываемую текстовую строку в заданном месте с помощью определяемых объектов Brush и Font. | 6 |
Equals(Object) | Определяет, равен ли заданный объект текущему объекту. (Унаследовано от Object.) | 1 |
ExcludeClip(Rectangle) | Обновляет вырезанную область данного объекта Graphics, чтобы исключить из нее часть, определяемую структурой Rectangle. | 1 |
ExcludeClip(Region) | Обновляет вырезанную область данного объекта Graphics, чтобы исключить из нее часть, определяемую структурой Region. | 1 |
FillClosedCurve(Brush, Point[]) | Заполняет внутреннюю часть замкнутой фундаментальной кривой, определяемой массивом структур Point. | 6 |
FillEllipse(Brush, Rectangle) | Заполняет внутреннюю часть эллипса, определяемого ограничивающим прямоугольником, который задан структурой Rectangle. | 4 |
FillPath(Brush, GraphicsPath) | Заполняет внутреннюю часть объекта GraphicsPath. | 1 |
FillPie(Brush, Rectangle, Single, Single) | Заполняет внутреннюю часть сектора, определяемого эллипсом, который задан структурой RectangleF, и двумя радиальными линиями. | 3 |
FillPolygon(Brush, Point[]) | Заполняет внутреннюю часть многоугольника, определяемого массивом точек, заданных структурами Point. | 4 |
FillRectangle(Brush, Rectangle) | Заполняет внутреннюю часть прямоугольника, определяемого структурой Rectangle. | 4 |
FillRegion(Brush, Region) | Заполняет внутреннюю часть объекта Region. | 1 |
Flush() | Вызывает принудительное выполнение всех отложенных графических операций и немедленно возвращается, не дожидаясь их окончания. | 2 |
IntersectClip(Region) | Обновляет вырезанную область данного объекта, включая в нее пересечение текущей вырезанной области и указанной структуры | 3 |
ResetClip() | Сбрасывает выделенную область g, делая ее бесконечной | 1 |
Подробнее еще о двух классах.
Класс Pen
Класс Pen определяет объект, используемый для рисования прямых линий и кривых. Этот класс не наследуется. Конструкторы класса (тоже пример перегрузки методов):
1) Pen(Color) инициализирует новый экземпляр класса Pen с указанным цветом.
2) Pen(Color, Single) инициализирует новый экземпляр класса Pen с указанными свойствами Color и Width. (Width — устанавливает ширину пера Pen, в единицах объекта Graphics, используемого для рисования
Например:
Pen redPen = new Pen(Color.Red); // толщина пера по умолчанию 1 пиксель
или используя промежуточную переменную green
Color green = Color.Green;
Pen greenPen = new Pen(green, 4.5f);
Можно вводить новый объект без указания явного имени пера (пример создания динамического объекта — пера):
g.DrawRectangle(new Pen(Color.Red, 3), r);
например, для рисования прямоугольника r красным пером толщиной 3 пикселя, используя графический контекст («холст») g.
Класс Brush
Класс 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);
Для первоначального привыкания к стилю ООП в графике рассмотрим первый пример рисования.
NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.
Источник: c-sharp.pro
HTML5 Canvas — простая программа рисования
Кроме рассмотренных ранее, холст имеет много других возможностей. Но на данном этапе вы обладаете достаточным объемом знаний, чтоб создать простую программу рисования на основе холста.
Код JavaScript для этой программы более объемный, чем в предыдущих примерах, но все равно на удивление простой. Мы рассмотрим эту программу по частям в следующих разделах.
Подготовка к рисованию
При загрузке страницы код получает объект холста canvas и подключает к нему функции для обработки нескольких событий JavaScript для разных движений мыши: onMouseDown, onMouseUp, onMouseOut и onMouseMove. (Как мы увидим далее, эти события управляют процессом рисования.) В то же самое время страница сохраняет холст в глобальной переменной canvas, а контекст рисования — в другой глобальной переменной context. Таким образом, эти объекты будут доступны для остального кода:
var canvas; var context; window.onload = function() < canvas = document.getElementById(«drawingCanvas»); context = canvas.getContext(«2d»); // Подключаем требуемые для рисования события canvas.onmousedown = startDrawing; canvas.onmouseup = stopDrawing; canvas.onmouseout = stopDrawing; canvas.onmousemove = draw; >
Чтобы начать рисовать, пользователь выбирает цвет и толщину линии, щелкнув по требуемым значкам в панели инструментов вверху окна рисования. Эти панели инструментов создаются с помощью простых элементов , отформатированных под светло-голубой фон и содержащих по несколько элементов , активируемых щелчком мыши:
— Цвет —
— Толщина —
— Операции-
Сохранить содержимое Canvas Очистить Canvas
Щелкните правой кнопкой мыши для сохранения .
body < background: white; >.Toolbar < float: left; font-family: ‘Trebuchet MS’; font-size: 14px; font-variant: small-caps; text-align: center; background: #F2F7FE; padding: 10px 15px 3px 10px; margin-bottom: 1px; margin-right: 1px; border: 1px solid #7B899B; >.Toolbar button < padding: 6px; margin: 7px 2px; font-variant: normal; font-size: 12px; >.CanvasContainer < clear: both; >canvas < border: 1px solid #7B899B; >img < padding: 2px; border: 2px solid #F2F7FE; >img:hover < border: 2px groove #E4F0FE; background: white; >img.Selected < border: 2px groove #E4F0FE; >#savedCopyContainer < display: none; >#savedCopyContainer img
Важной частью этой разметки является атрибут onclick элемента . При щелчке пользователя по значку ручки определенного цвета элемент
вызывает функцию changeColor(). Эта функция принимает два параметра — новый цвет, который совпадает с цветом выбранного значка, и ссылки на элемент
var previousColorElement; function changeColor(color, imgElement) < // Меняем текущий цвет рисования context.strokeStyle = color; // Меняем стиль элемента , по которому щелкнули imgElement.className = «Selected»; // Возвращаем ранее выбранный элемент
в нормальное состояние if (previousColorElement != null) previousColorElement.className = «»; previousColorElement = imgElement; >
Код функции changeColor() выполняет две основные задачи.
Во-первых, он устанавливает свойство контекста strokeStyle в значение соответствующего нового цвета. Для этого требуется всего лишь одна строка кода. Во-вторых, код изменяет оформление элемента , по которому щелкнули, заключая его в рамку, чтобы было видно, какой цвет является текущим. Выполнение этой операции требует больше работы, т.к. необходимо отслеживать цветовой элемент
Функция changeThickness() выполняет почти идентичную работу, только она изменяет значение свойства контекста lineWidth в соответствии с выбранной толщиной линии:
// Отслеживаем элемент для толщины линии, по которому ранее щелкнули var previousThicknessElement; function changeThickness (thickness, imgElement) < // Изменяем текущую толщину линии context.lineWidth = thickness; // Меняем стиль элемента
Рассмотренный выше код подготавливает холст для рисования, но рисовать еще рано. Для этого нужно добавить код, который собственно выполняет рисование, что и делается в следующем разделе.
Рисование на холсте
Процесс рисования начинается, когда пользователь щелкает мышью по холсту. Для отслеживания, когда осуществляется рисование, в программе используется глобальная переменная isDrawing, информирующая остальной код программы, можно ли работать с контекстом рисования.
Как мы видели ранее, событие onMouseDown связано с функцией startDrawing(). Эта функция устанавливает переменную isDrawing, создает новый путь, а потом устанавливает начальную позицию рисования, подготовив таким образом холст для рисования:
function startDrawing(e) < // Начинаем рисовать isDrawing = true; // Создаем новый путь (с текущим цветом и толщиной линии) context.beginPath(); // Нажатием левой кнопки мыши помещаем «кисть» на холст context.moveTo(e.pageX — canvas.offsetLeft, e.pageY — canvas.offsetTop); >
Чтобы наша программа работала корректно, рисование должно начинаться в текущей позиции, т.е. там, где находится указатель мыши, когда пользователь нажимает левую кнопку. Но задача получения правильных координат этой точки несколько сложновата.
Событие onMouseDown предоставляет координаты курсора мыши (через свойства pageX и pageY, показанные в этом примере), но это координаты относительно всей страницы. Чтобы вычислить соответствующие координаты холста, необходимо от координат левого верхнего угла окна браузера отнять расстояние до левого верхнего угла холста.
Собственно рисование происходит, когда пользователь двигает мышь, удерживая нажатой левую кнопку. При каждом перемещении мыши, даже на один пиксель, активируется событие onMouseMove и исполняется код функции draw(). Если переменная isDrawing установлена, код вычисляет текущие координаты холста (т.е координаты точки, в которой в данный момент находится указатель мыши), а потом вызывает метод lineTo(), который добавляет путь соответствующего отрезка линии, после чего вызывается метод stroke(), который прорисовывает эту линию:
function draw(e) < if (isDrawing == true) < // Определяем текущие координаты указателя мыши var x = e.pageX — canvas.offsetLeft; var y = e.pageY — canvas.offsetTop; // Рисуем линию до новой координаты context.lineTo(x, y); context.stroke(); >>
Если пользователь продолжает перемещать мышь, снова вызывается функция draw(), опять добавляя отрезок к уже нарисованной линии. Этот отрезок настолько короткий — длиной всего лишь в один или два пиксела, что он даже не выглядит, как прямая линия в начале рисования.
Наконец, когда пользователь отпускает кнопку мыши или выводит курсор за пределы холста, срабатывает событие onMouseUp или onMouseOut соответственно. Оба эти события активируют функцию stopDrawing(), которая указывает приложению прекратить рисование:
function stopDrawing()
На данном этапе мы рассмотрели все аспекты рисования:
Теперь перейдем к обсуждению функций очистки холста или сохранения созданного рисунка. Для этих целей предназначены две кнопки на панели инструментов внизу холста. Нажатие кнопки «Очистить Canvas» вызывает функцию clearCanvas(), которая полностью очищает поверхность холста с помощью метода контекста clearRect():
function clearCanvas()
Операция сохранения содержимого холста более сложна, и мы посвятим ей отдельный раздел.
Сохранение содержимого Canvas
Задача сохранения содержимого холста требует рассмотрения множества опций. Прежде всего, нужно решить, каким образом получить данные рисунка. Для решения этой задача холст предоставляет три возможных подхода:
Использовать URL данных
При этом подходе содержимое холста преобразуется в файл изображения, которое потом переводится в последовательность символов, оформленных в виде URL. Это позволяет получить аккуратный и компактный способ для перемещения данных изображения (например, его можно передать элементу и отослать на веб-сервер). В нашей программе рисования будем использовать этот подход.
Использовать метод getImageData()
Этот подход позволяет получить «сырые» пиксельные данные, которыми можно потом манипулировать как угодно.
Сохранять список «шагов».
Например, можно организовать массив, содержащий список всех линий, нарисованных на холсте. Эти данные можно потом сохранить и использовать для воспроизведения изображения. Данный подход требует меньше места для хранения изображения, а также предоставляет большую гибкость для последующей работы с ним.
Но это еще не все. Определившись с типом содержимого для сохранения, нужно решить, где это содержимое сохранить. Возможны, среди прочих, следующие опции:
- В файле изображения . Например, содержимое холста сохраняется в виде файла формата PNG или JPEG на локальном жестком диске художника. Это подход, который применяется в нашей программе рисования, и мы его рассмотрим далее.
- В локальной системе хранения .
- На веб-сервере . После передачи данных веб-серверу последний может сохранить их в файле или базе данных и предоставить при следующем посещении страницы пользователем.
var url = canvas.toDataURL(«image/jpeg»);
Но если браузер не может предоставить требуемый формат, он опять выдаст изображение в формате PNG, преобразованное в длинную строку. Что же собой представляет URL данных? Технически это просто длинная строка символов, закодированных алгоритмом Base64, которая начинается с текста: data:image/png;base64. Это выглядит как бессмыслица, по крайней мере, для людей, т.к. эти данные предназначены для понимания компьютерными программами, например браузерами. URL данных для содержимого холста выглядит примерно таким образом:
data:image/png;base64, iVBORwOKGgoAAAANSUhEUgAAAfQAAAEsCAYAAAA2uOHXAAAAA .
Таким образом, задача преобразования данных изображения в URL данных не представляет никаких трудностей. Но что можно делать дальше с этим URL данных? Можно отправить его на веб-сервер для длительного хранения. Пример выполнения этой операции с помощью кода PHP представлен на веб-странице HTML5: Saving Canvas Image Data Using PHP And Ajax.
Но возможности для сохранения данных на стороне клиента несколько ограничены. Некоторые браузеры позволяют перейти непосредственно к URL данных. Это означает, что для перехода к изображению можно использовать следующий код:
window.location = canvas.toDataURL();
Более надежным методом будет передать URL данных в элемент , что и делает наша программа рисования:
function saveCanvas() < // Находим элемент var imageCopy = document.getElementById(«savedImageCopy»); // Отображаем данные холста в элементе
imageCopy.src = canvas.toDataURL(); // Показываем элемент , делая изображение видимым // делая изображение видимым var imageContainer = document.getElementById(«savedCopyContainer»); imageContainer.style.display = «block»; >
Этот код не совсем сохраняет данные изображения, т.к. изображение еще не сохранено в файле. Но для этого требуется всего лишь один шаг — просто щелкнуть правой кнопкой мыши по уменьшенному изображению в панели под холстом и в открывшемся контекстном меню выбрать команду «Сохранить картинку как». Это не так удобно, как закачка файла или диалоговое окно Сохранить, но единственный способ, который надежно работает во всех браузерах.
Источник: professorweb.ru
Как создать программу для рисования
Эта статья посвящена тому, как создать приложение типа «MS Paint» в приложении типа Windows Presentation Foundation. Статья ориентирована на средний уровень пользователя или начальный уровень разработчика. Для работы понадобится среда разработки Visual Studio 2013.
Запустите Visual Studio 2013, выберите тип проекта из шаблона Visual C# / Windows / WPF Application (Рис.1) и назовите его WPFApp2 (ну или как хотите).
Рис.1. Создать WPF Application в Visual Studio 2013
В свойствах приложения (Properties) выберите нужный фон приложения, заголовок приложения и другие основные настройки (Рис.2). Я решил выбрать темно-синий градиент.
Рис.2. Выбор фона для WPF приложения
В окне Toolbox по умолчанию довольно мало элементов, а для «рисовалки» понадобится контрол InkCanvas. Чтобы его добавить в список элементов управления, нужно в свободном месте окна ToolBox нажать правой кнопкой мыши и выбрать пункт «Choose Items» (Рис.3)
Рис.3. Добавление элементов управления
В открывшемся окне во вкладке «WPF Components» выберите «InkCanvas» и нажмите «OK» (Рис.4)
Рис.4. Добавление InkCanvas
Теперь ператащите из окна ToolBox элемент InkCanvas в окно проекта. В XAML-файле укажите имя контролу (Name) и размеры. В принципе, это можно делать и через окно Properties (Рис.5)
Рис.5. Установка свойств элементу управления через окно Properties
В принципе, первая часть приложения готова. Если запустить приложение, нажав F5, то сможете создать такую картину:
Рис.6. Простейшая рисовалка своими руками
Приложение позволяет только рисовать, нет возможности ни очистить область, ни выбрать цвет и размер кисти, ни сохранить изображение.
Об этом будет в дальнейших публикациях.
Источник: markimarta.ru