Как построить график в windows forms c
На примере графики наглядно видны преимущества ООП, смысл использования классов, их методов и свойств. Добавляя в пространство имен своего проекта соответствующие библиотеки, вы получаете сразу набор инструментов, необходимых для графики. Это графические примитивы (линии, прямоугольники, эллипсы и т.п.), перо для черчения, кисть для закраски и много других полезных объектов и методов.
Пространство имен System.Drawing (Рисование) обеспечивает доступ к функциональным возможностям графического интерфейса GDI+ , используя около 50 (!) классов, в том числе класс Graphics. Чуть позже мы будем использовать дополнительные пространства имен System.Drawing.Drawing2D, System.Drawing.Imaging, System.Drawing.Printing, System.Drawing.Text, расширяющие функциональные возможности библиотеки System.Drawing.
Класс Graphics предоставляет методы рисования на устройстве отображения (другие термины — графический контекст, «холст»). Определимся сразу, на чем мы хотим рисовать. Далее в примерах он обозначается как объект 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
Класс 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
Класс Brush
Для первоначального привыкания к стилю ООП в графике рассмотрим первый пример рисования.
К сожалению, получается совсем не то, что нужно:
Я думаю, что проблема в том, как я записываю функцию. Может ли кто-то помочь мне решить это?
- Вопрос задан более года назад
- 12824 просмотра
А так у вас строится y=x*x*x/(2*a-x). Кстати, выражение знаменателя тоже зачем-то у вас делится на 2.
public Form1() InitializeComponent();
int a = 4, m;
for (int i = 1; i<50; i++) m = ((2 * a) - i);
if (m == 0) m = 1;
>
chart1.Series[0].Points.AddXY((i), ((i*i*i)/m)/2);
>
>
Но все равно получается не так, как нужно:
Тут у вас сразу несколько ошибок:
1. Нужно явно приводить к double иначе при делении двух int получите тоже целое.
2. Вы берете очень большие границы. Рост знаменателя намного превышает скорость роста числителя. Сами посмотрите: возведите 50 в куб, что получите? График вы конечно построите, но наглядности будет немного.
Что более важно: ваш отрезок OA = 2*a, а это значит что ваша правая граница точно должна быть меньше чем 2*a;
3. Посмотрите как задана функция - в виде квадрата. Извлекая корень вы должны не забывать про нижнюю ветку - ту которую дают отрицательные значения y.
Насколько мне известно возможности стандартного контрола довольно ограничены - вам придется заносить значения во вторую линию.
Собирая все вместе, попробуйте что-то вроде такого:
Здесь 1 (x < 2 * a - 1) вычитается только для примера, чтобы вы сравнили результат. В реальности вам придется определять границу более сложным путем чтобы для разных a и левой границы (x) получать наглядное представление. Но, по крайней мере, у вас есть от чего отталкиваться.
Используя данный пример, можно создавать собственные программы для построения графиков других функций. По желанию можно модернизировать работу программы по своему усмотрению.
Содержание
Поиск на других ресурсах:
Условие задачи
Задана формула функции двух переменных z = sin(x) + cos(y) . Разработать приложение, которое рисует график этой функции в отдельной форме.
Дополнительно реализовать поворот графика влево, вправо, вверх, вниз. Также нужно выводить оси OX , OY , OZ .
⇑
Математическая постановка задачи
Построение графика функции двух переменных есть математически решаемой задачей, в которой используются известные формулы вычисления.
График функции двух переменных z(x,y) строится в параллелепипеде с размерами (xx1, xx2) , (yy1, yy2) , (zz1, zz2) .
Для использования поворота системы в 3-мерном пространстве возникает понятие точки ( x0 , y0 , z0), относительно которой происходит поворот системы координат.
Также возникает понятие углов:
-
(альфа) – поворот системы относительно оси OZ ; (бета) – поворот системы относительно оси OX .
Сдвиг в точку ( x0 , y0 , z0 ) с учетом поворота на углы и описывается известными соотношениями
После перемножения матриц получаем формулу для вычисления:
По этой формуле будет происходить преобразование системы координат и масштабирование (рисунок 1).
Рис. 1. Сдвиг и поворот системы координат
Необходимо определиться, в какой плоскости монитора будут лежать оси координат OX , OY , OZ . Принимаем, что в плоскости монитора лежат оси OX и OY . А ось OZ перпендикулярна экрану.
Координаты расчетной точки (x, y) прижимаются к точке (0, 0) по формулам:
где A , a – коэффициенты перспективы, которые подбираются экспериментально в зависимости от функции.
⇑
Выполнение
1. Создание проекта как Windows Forms Application
⇑
2. Создание формы Form1 .
Создать форму по образцу, как показано на рисунке 2.
Настроить следующие свойства компонент и формы:
⇑
3. Создание формы Form2 .
Создать новую форму. Подробный процесс создания новой формы описывается здесь .
Разместить на форме четыре компонента типа Button. Автоматически создается четыре объекта с именами button1, button2, button3, button4.
Настроить свойства компонент и формы следующим образом:
Приблизительный вид формы Form2 изображен на рисунке 3.
4. Ввод внутренних переменных в форму Form2 .
Все внутренние переменные, использующиеся для организации вывода графика, размещаются в классе формы Form2. Поэтому, сначала надо активизировать модуль « Form2.pas ».
В модуль формы Form2 вводятся следующие внутренние переменные с классом видимости private:
- xx1, xx2, yy1, yy2 – соответствуют координатам точек, которые отображаются на экране монитора;
- массивы xx и yy предназначены для вывода плоскости из 4-х точек. Область определения функции z = f(x, y) разбивается на прямоугольники, на любом из которых функция экстраполируется ребрами четырехугольника.
В разделе public вводятся:
- переменные X_min , Y_min , X_max , Y_max вещественного типа, которые представляют реальные координаты параллелепипеда, в котором выводится график функции. Эти переменные заполняются из основной формы Form1 экспериментальным путем:
- переменные alfa, beta вещественного типа, которые отображают углы наблюдения за графиком функции. Заполняются из главной формы Form1;
- переменные x0, y0, z0 вещественного типа. Отображают величины из главной формулы вычисления (см. математическую постановку задачи);
- переменная A вещественного типа. Представляет коэффициент перспективы и подбирается экспериментально;
- переменная f_show логического типа используется для указания того, что нужно перерисовать график, в случае изменения положения углов alfa и beta.
После введения переменных в текст программы, фрагмент класса формы Form2 имеет вид:
Переменные, имеющие идентификатор доступа public, заполняются из формы Form1 .
⇑
5. Программирование внутренних методов в форме Form2 .
В текст класса Form2 вводятся три дополнительных метода:
- функция преобразования системы координат и масштабирования Zoom_XY() ;
- функция func() для которой выводится график;
- функция рисования графика Show_Graphic().
Листинг метода преобразования системы координат следующий:
Листинг метода func() следующий.
В этом методе вместо строки
можно сделать вставку собственной функции.
Непосредственный вывод графика функции реализован в методе Show_Graphic() . Листинг метода Show_Graphic() следующий.
Объясним некоторые фрагменты кода в методе Show_Graphic().
Область определения функции z = f(x,y) разбивается на прямоугольники, на любом из которых функция экстраполируется с ребрами четырехугольника. Построение четырехугольников на экране реализуется с помощью метода DrawLine().
После очистки канвы происходит рисование осей координат и методом DrawLine() выводятся фрагменты поверхности.
При рисовании поверхности, из метода Show_Graphic() вызывается метод Zoom_XY(), что осуществляет преобразование и масштабирование из реальных координат в экранные координаты.
⇑
6. Программирование события Paint формы Form2.
Обработчик события Form2_Paint() получает два параметра. Первый параметр типа System.Object , второй параметр типа PaintEventArgs .
Параметр типа PaintEventArgs содержит объект Graphics, необходимый для рисования на поверхности формы.
Листинг обработчика события Form2_Paint() следующий.
⇑
7. Программирование обработчиков событий клика на кнопках button1, button2, button3, button4.
Поворот графика происходит в момент, когда пользователь делает клик на одной из кнопок, размещенных на форме Form2 (элементы управления button1, button2, button3, button4).
Отображение графика зависит от внутренних переменных alfa и beta. Переменная alfa содержит угол поворота относительно оси OZ . Переменная beta содержит значение угла поворота вокруг оси OX .
Поэтому, в обработчиках событий происходит изменение значений alfa и beta на некоторую величину. По желанию, можно установить собственную величину изменения alfa и beta.
Листинг обработчиков событий приведен ниже.
В вышеприведенных обработчиках событий, событие Paint генерируется явно с помощью унаследованного метода Invalidate(). Этот метод делает перерисовывание всей клиентской области программным путем.
Метод Invalidate() имеет несколько перегруженных вариантов. Например, если нужно обновить заданный прямоугольник, то нужно создать такой код:
⇑
8. Программирование обработчиков событий MouseDown, MouseMove и MouseUp.
Для осуществления поворота графика с помощью мышки нужно запрограммировать соответствующие обработчики событий.
Если нажать клавишу мыши и удерживать ее нажатой над формой Form2, а потом отпустить, то генерируются такие события (рисунок 4):
- MouseDown – генерируется, если пользователь делает клик мышкой на форме Form2;
- MouseMove – генерируется, если пользователь перемещает мышку над формой Form2 (независимо, нажата ли одна из кнопок мышки);
- MouseUp – генерируется, если пользователь отпускает кнопку мышки после нажатия.
⇑
9. Листинг модуля « Form2.cs ».
Ниже приведен полный текст файла ” Form2.cs ”, который соответствует форме Form2.
⇑
10. Программирование события клика на кнопке button1 формы Form1 (вызов формы рисования графика функции).
При клике на кнопке button1 из формы Form1 может выводиться график функции.
Обработчик события клика на кнопке Button1 имеет вид.
11. Запуск программы.
После запуска программы на выполнение, форма графика функции изображена на рисунке 5.
В данной главе мы рассмотрим процесс создание программы, задачей которой будет визуализация графика заданной функции. Особенностью программы будет то, что в ней будет анимированно демонстрироваться то, как меняются значения функции на графике.
Это будет реализовано следующим образом: по графику двигается красная точка, принимающая значения y для заданного x в нашем графике (по всей видимой области). Помимо этого возле курсора будут визуализироваться его координаты (рис. 1).
Окно должно иметь форму, как показано на рисунке 1.
Добавьте в проект таймер, назовите его (параметр name в свойствах таймера) PointInGrap и установите в его свойствах интервал 30 миллисекунд. После этого щелкните по нему дважды, чтобы создалась функция PointInGrap_Tick, отвечающая за обработку события ontimer.
Теперь, когда основа приложения создана, мы перейдем к исходному коду. Он будет основан на 7 функциях, которые мы сейчас рассмотрим, но сначала перед кодом функции-конструктора класса добавьте инициализацию следующих переменных:
Перед каждой переменной закомментировано ее назначение, так что вопросов возникнуть не должно.
Теперь вернемся к нашим 7 функциям.
Первая функция – это обработчик события загрузки формы Form1_Load. Здесь при загрузке приложения будет произведена инициализация OpenGL для последующей визуализации.
Инициализацию OpenGL с двухмерной проекцией мы рассмотрели в предыдущей части главы, так что здесь все должно быть понятно. Единственным отличием является то, что код стал немного более подробным. Код этой функции:
Как видите, почти ничего не изменилось. Теперь обратимся к функции PointInGrap_Tick. Эта функция вызывается с задержкой в 30 миллисекунд.
В ней мы ведем отсчет того, из какого элемента массива с координатами графика мы сейчас возьмем координаты, которые используем для рисования красной точки.
Отсюда так же вызывается функция Draw, отвечающая за визуализацию.
Код этой функции:
Теперь перед тем как перейти к функциям, отвечающим за визуализацию, мы рассмотрим несолько небольших вспомогательных функций.
Начтем с функции AnT_MouseMove. Эта функция добавляется созданием события MouseMove для элемента SimpleOpnGLControl (AnT). Событие создается аналогично тому, как мы его создавали в главе 2.2. Только в данном случае мы переходим к свойствам элемента AnT и уже в них переходим во вкладку Event и добавляем событие MouseMove.
В данной функции мы производим сохранение текущих координат мыши, чтобы в будущем использовать их при визуализации графика, а также производим вычисление размеров линий, которые будут по нормалям соединять координаты указателя мыши с координатными осями (две красные линии на рисунке 1).
Код этой функции выглядит следующим образом:
Теперь рассмотрим функцию, которая будет осуществлять визуализацию текстовых строк. Эта функция устанавливает координаты вывода растровых символов в соответствии с координатами, переданными в параметрах x и y, а затем в цикле перебирает все символы из указанной в параметре строки текста. Каждый из символов визуализируется с помощью функции. В этой функции указывается шрифт для вывода и переменная типа char для визуализации.
Код функции выглядит следующим образом:
Следующая функция, которой мы коснемся - это функция, вычисляющая координаты для построения графика. В ней инициализируется массив координат и производится вычисление всех координат графика в зависимости от указанного диапазона значений x и шага приращения этих значений.
Обратите внимание на то, что при инициализации массива для хранения координат должно быть указано такое количество элементов массива, чтобы в дальнейшем их хватило для размещения всех координат, иначе произойдет исключение, так как программа в процессе работы попытается обратиться к области памяти, которая ей не принадлежит.
Код этой функции с подробными комментариями:
Функция, выполняющая визуализацию графика
Так как визуализацию графика можно отнести к конкретной подзадаче функции визуализации сцены (и чтобы не загромождать функцию визуализации сцены), мы вынесем визуализацию графика в отдельную функцию.
В этой функции сначала будет проверен флаг, сигнализирующий о том, что координаты графика вычислены и занесены в массив (переменная not_calculate). В том случае, если флаг указывает, что просчета значений еще не было, вызывается функция, которая посчитает значения координат точек графика и заполнит ими массив.
Далее реализуется проход циклом for по массиву значений координат точек графика и их визуализация, причем мы визуализируем не точки, а объединяем эти точки в линию, основываясь на значении координат точек, как на вершинах.
По завершению отрисовки графика производится рисование красной точки в тех координатах, до которых мы дошли, последовательно перебирая значения элементов в массиве координат.
Исходный код данной функции:
И теперь нам осталось просмотреть последнюю функцию – функцию Draw.
В ней визуализируется координатная сетка под графиком, координатные оси и буквы для их обозначений, а также вызывается функция рисования графика и выводятся координаты мыши с линиями, соединяющими указатель мыши и оси координат.
Читайте также: