Как построить график в c visual studio
Используем возможности языка C# для разработки программы рисования графиков функций.
Откроем среду программирования C#, выбирая последовательно Пуск -> Все программы -> Microsoft Visual C# 2008 Express Edition.
На начальной странице (Start Page) выберем пункт Create: Project. В результате появится диалоговое окно выбора типа создаваемого проекта.

В качестве типа создаваемого проекта выберем Windows Application, в поле Name: зададим имя проекта (например, DrawFunction) и нажмем кнопку OK.

В результате получаем основу нашего проекта, который нужно доработать, чтобы он мог выполнять требуемые функции.
Щелчком мыши на форме Form1, выберем ее и в окне свойств (Properties) изменим свойство Text, заменив Form1 на «График функции». Изменим также имя формы, по которому к ней можно обращаться из программы, заменив в свойстве (Name) Form1 на frmMain. Необходимо сразу отметить и запомнить, что это два совершенно разных свойства, используемых для различных целей, и никогда их не путать.
Графический интерфейс нашего приложения будет состоять из окна, в котором будет отображаться график функции и кнопки, по щелчку на которой будет рисоваться этот график.
Для формирования графического интерфейса приложения наведем мышку на иконку Toolbox, расположенную слева и сверху от формы, и в появившемся окне элементов графического интерфейса выберем PictureBox, и перенесем его на форму. Для этого нужно щелкнуть левой кнопкой мыши в том месте формы, где должен находиться левый верхний угол элемента и, не отпуская кнопку, перетащить мышь в то место, где должен находиться правый нижний угол элемента, и там отпустить кнопку.
Для появившегоя элемента PictureBox изменим его свойство (Name) с pictureBox1 на graphWind. Кроме того, рекомендуется изменить свойство BorderStyle с None на Fixed3D, а также свойство BackColor на белый (White).

Аналогичным образом разместим на форме кнопку Button, выбрав ее с панели элементов управления Toolbox. Получившаяся форма должна иметь примерно следующий вид.

Основная работа приложения — рисование графика функции, будет выполняться при щелчке на кнопке «Нарисовать график». Чтобы вставить код обработчика соответствующего события, нужно дважды щелкнуть на кнопке и в результате откроется окно кода с требуемым заголовком нужной процедуры.
private void button1_Click(object sender, EventArgs e)
Вставьте в этот обработчик следующий код.
private void button1_Click(object sender, EventArgs e) < Graphics g = graphWind.CreateGraphics(); Pen myPen = new Pen(Color.Blue); int nmbInterv = 100; float xmin = 0, xmax = 2, ymin = 0, ymax = 4; float xstep = (xmax - xmin) / nmbInterv; float kx = graphWind.Width / xmax, ky = graphWind.Height / ymax; float x1 = xmin, y1 = x1 * x1, x2, y2; for (int i = 0; i < nmbInterv; i++) < x2 = x1 + xstep; y2 = x2 * x2; g.DrawLine(myPen, kx * x1, graphWind.Height - ky * y1, kx * x2, graphWind.Height - ky * y2); x1 = x2; y1 = y2; >>
Для проверки работы программы достаточно нажать клавишу F5. В результате, если все сделано правильно, должно появиться окно приложения. После нажатия кнопки «Нарисовать график» в окне должен появиться график функции.

Данная программа представляет грубую заготовку для первоначального ознакомления с основами построения графиков функций программными седствами языка C#. Определите, что можно и нужно добавить в данное приложение, чтобы оно стало более удобным и более функциональным, и постарайтесь самостоятельно реализовать такие возможности.
Как построить график в c visual studio
БлогNot. Visual C++: построение графиков с интерпретацией введённой пользователем функции
Visual C++: построение графиков с интерпретацией введённой пользователем функции
В принципе, вся нужная информация есть вот здесь, сделаем по ней законченный проект.
Структура основной формы показана на рисунке, компоненты в panel1 перечислены по порядку в форме слева направо, что обеспечивает и нормальный порядок обхода полей по клавише табуляции.

основная форма приложения
Текстовым полям можно ограничить максимальный размер вводимой строки (свойство MaxLength ). Также panel1 расположена со свойством Dock=Top , а chart1 со свойством Dock=Fill . Это обеспечит нормальное взаимодействие компонент при изменении размеров окна. У самой формы выставлены Size и MinimumSize в значение 640; 400 — чтобы не «исчезали» кнопки при уменьшении окна.
Текстовым полям также даны значения по умолчанию, дробные части вещественных чисел при этом отделены точкой, а не запятой — будем так делать во всём проекте.
Как альтернатива, можно формировать вещественные значения полей динамически в зависимости от текущего разделителя (например, по событию Load формы 1):
double x1=3.14; this->x1->Text = x1.ToString();
В форму также добавлено глобальное свойство типа NumberFormatInfo
public: System::Globalization::NumberFormatInfo ^ nfi;
которое проинициализировано в её конструкторе:
Form1(void) < InitializeComponent(); nfi = gcnew System::Globalization::NumberFormatInfo(); nfi->NumberDecimalSeparator = "."; //"принудительная" точка разделителем целой и дробной части // //TODO: добавьте код конструктора // >
Основная работа выполняется по нажатию на кнопку OK ( button1_Click ). Сначала проверяем допустимость введённых данных с помощью пары служебных методов Parse (получить число) и Check (проверить правильность записи функции, попробовав получить её значение от 1-го аргумента). Потом метод Go делает цикл по нужным значениям аргумента, формируя диаграмму. Если возникает ошибка парсера, о ней выводится сообщение, но программа не завершается. Просто в данных не будет какой-то пары значений.
Парсер тот же, что по ссылке выше. Вот полный код фрагмента:
#pragma endregion private: bool Parse (String ^s, double &a) < System::IFormatProvider ^ provider = System::Globalization::CultureInfo::GetCultureInfo("en-US"); bool A = Double::TryParse(s,System::Globalization::NumberStyles::Number, provider,a); return A; >private: bool Check (String ^Str,double x1) < TParser *parser = new TParser(); try < double x=x1; Str=Str->Replace("x",x.ToString(nfi)); char *p = (char*) (Runtime::InteropServices::Marshal::StringToHGlobalAnsi (Str)).ToPointer (); parser->Compile(p); parser->Evaluate(); return true; > catch (. ) < return false; >> private: void Go (String ^S,double x1, double x2, double dX) < TParser *parser = new TParser(); using namespace System::Windows::Forms::DataVisualization::Charting; using namespace System::Collections::Generic; using namespace System::Drawing::Drawing2D; using namespace System::Drawing; using namespace Runtime::InteropServices; Dictionary f1 = gcnew Dictionary(); String ^ Str; double x; char *p; chart1->Series[0]->ChartType = SeriesChartType::Line; chart1->Series[0]->MarkerStyle = MarkerStyle::Circle; ArrayList points = gcnew ArrayList(); try < for (x=x1; xReplace("x",x.ToString(nfi)); p = (char*) (Marshal::StringToHGlobalAnsi(Str)).ToPointer(); parser->Compile(p); parser->Evaluate(); f1.Add(x, parser->GetResult()); > > catch(TError error) < System::String ^ str1 = gcnew System::String (error.error); System::String ^ str2 = gcnew System::String (error.pos.ToString()); MessageBox::Show ("Ошибка " + str1 + " в позиции строки разбора " + str2+" для x = "+x, "Ошибка парсера",MessageBoxButtons::OK); //return; >chart1->Series[0]->LegendText = S; chart1->Series[0]->Color = System::Drawing::Color::Green; chart1->Series[0]->BorderWidth = 2; chart1->Series[0]->Points->DataBindXY(f1.Keys, f1.Values); > private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) < double x1,x2,dX; String ^ s = textBox1->Text; this->chart1->Visible=false; if (Parse(this->x1->Text,x1)==false || Parse(this->x2->Text,x2)==false || Parse(this->dX->Text,dX)==false) < MessageBox::Show ("Введите числовые значения x1,x2,dx","Ошибка",MessageBoxButtons::OK); return; >if (x1>x2 || x1+dX>x2) < MessageBox::Show ("Введите x1this->chart1->Visible=true; if (!Check (s,x1)) < MessageBox::Show ("Введите верную функцию, не могу взять значение от 1-го аргумента", "Ошибка",MessageBoxButtons::OK); return; >Go (s, x1, x2, dX); > private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) < Form2 ^F2 = gcnew Form2; using namespace System::Windows::Forms::DataVisualization::Charting; for each (DataPoint ^p in chart1->Series[0]->Points) < F2->Do (p->XValue, p->YValues[0],nfi); > F2->Show(); >
Единственная новая по отношению к статье мелочь —
Если национальные стандарты предполагают, что дробная часть вещественного числа отделяется от целой запятой, а не точкой, вместо оператора
Str=Str->Replace("x",x.ToString());
System::Globalization::NumberFormatInfo ^ nfi = gcnew System::Globalization::NumberFormatInfo(); nfi->NumberDecimalSeparator = "."; //для C++ нужна "принудительная" точка разделителем целой и дробной части //. Str=S->Replace("x",x.ToString(nfi));
Добавим в проект вторую форму, куда можно будет выводить таблицы данных из диаграммы. Для этого обратимся к меню Проект — Добавить новый элемент — Форма Windows Forms и назовём её Form2 . На вторую форму добавим DataGridView , поставим ему свойства Dock=Fill , ScrollBars=Vertical и подготовим 2 столбца для вывода значений X и Y:

вторая форма — вывод таблицы значений функции
У этой формы будет единственный публичный метод — принять пару значений (x,y) и добавить их в таблицу:
#pragma endregion public: void Do (double x, double y, System::Globalization::NumberFormatInfo ^ nfi) < dataGridView1->Rows->Add(1); int i=dataGridView1->RowCount-1; dataGridView1->Rows[i]->Cells[0]->Value = Math::Round(x,3).ToString(nfi); dataGridView1->Rows[i]->Cells[1]->Value = Math::Round(y,3).ToString(nfi); >
Такой код метода Do работает при установке свойства
dataGridView1->AllowUserToAddRows = false
так как при значении true в таблице есть «дополнительная» пустая строка, которая тоже участвует в нумерации.
А вызывать этот метод будет вторая кнопка tab с первой формы (функция button2_Click ), при этом, сначала создастся новый экземпляр Form2 , чтобы можно было сравнить несколько таблиц:
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) < Form2 ^F2 = gcnew Form2; using namespace System::Windows::Forms::DataVisualization::Charting; for each (DataPoint ^p in chart1->Series[0]->Points) < F2->Do (p->XValue, p->YValues[0]); > F2->Show(); >
Чтобы это сработало, заинклудьте заголовки второй формы в начале кода Form1.h :
#pragma once #include "parser.h" #include "Form2.h" namespace Lab4 < //.
Разумеется, сам парсер тоже подлючён. Это весь проект, можно собирать. Вот пример работы программы:

пример работы программы
Выражения в парсере пишутся "не совсем на C++", загляните в файл parser.cpp и увидите это, ещё лучше, можете модифицировать код парсера под свои нужды. Ну и ещё много что можно улучшить, а я выложу проект в текущем "образовательном" состоянии.
P.S. Для совместимости с Visual Studio 2015 достаточно сделать вот такой главный файл проекта Lab4.cpp :
// Lab4.cpp: главный файл проекта. #define _CRT_SECURE_NO_WARNINGS #include "stdafx.h" #include "Form1.h" using namespace Lab4; [STAThreadAttribute] int main(void) < // Включение визуальных эффектов Windows XP до создания каких-либо элементов управления Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false); // Создание главного окна и его запуск Application::Run(gcnew Form1()); return 0; >
- округлять вводимые и вычисляемые значения до некого удобного количества знаков в дробной части;
- ограничить максимальное количество узлов сетки, например, некой константой maxCollectionSize . При "слишком большом" размере коллекции Dictionary приложение может зависнуть, а какой размер "слишком большой", знает только Studio;
- найти минимальное и максимальное значения функции, назначив их затем меткам оси Y, выполнить ту же работу и для оси X;
- следить, не получилось ли при расчёте "не-число" Y с помощью isnan(y) || isinf(y) ;
- следить, не добавляются ли повторно в коллекцию элементы с тем же ключом, с помощью ContainsKey и т.д.
Вот набросок чуть "улучшенного" проекта для Studio 2015:
P.P.S. Решение едва ли предназначено для консольных приложений из-за не слишком удобных преобразований между строками библиотеки .NET и "классическими" строками std::string или char * . Тем не менее, поизвращаться, конечно, можно, скажем, вот такой код главного модуля проекта годится для консольного приложения Visual Studio 2015:
#define _CRT_SECURE_NO_WARNINGS #include #include #include "parser.h" using namespace std; char *str_replace (char *orig, char *rep, char *with) < //Замена строки char * на char * char *result; char *ins; char *tmp; int len_rep; int len_with; int len_front; int count; if (!orig || !rep) return NULL; len_rep = strlen(rep); if (len_rep == 0) return NULL; if (!with) with = ""; len_with = strlen(with); ins = orig; for (count = 0; tmp = strstr(ins, rep); ++count) < ins = tmp + len_rep; >tmp = result = new char [strlen(orig) + (len_with - len_rep) * count + 1]; if (!result) return NULL; while (count--) < ins = strstr(orig, rep); len_front = ins - orig; tmp = strncpy(tmp, orig, len_front) + len_front; tmp = strcpy(tmp, with) + len_with; orig += len_front + len_rep; >strcpy (tmp, orig); return result; > void Go (char *p, double x1, double x2, double dX) < TParser *parser = new TParser(); char xstr[80]; try < for (double x = x1; x Compile(p2); parser->Evaluate(); cout GetResult(); delete p2; > > catch (TError error) < cout delete parser; > int main() < double x1 = 0, x2 = 2 * M_PI, dx = M_PI / 10; //Или ввести откуда-то границы по оси X и шаг char *p = "sin(x)+x/2"; //Или получить строку с выражением f(x) откуда-то Go (p, x1, x2, dx); cin.get(); return 0; >
Как видно из примера, нам пришлось дополнительно написать собственную функцию str_replace для замены строки char * на другую строку, чтобы обеспечить циклическую подстановку значений x в табулируемую функцию f(x) .
А вот архив с этим проектом Visual Studio 2015, с точностью до платформы (выбирается вверху из списков "Конфигурации решения", "Платформы решения") должно работать везде 🙂 Конечно же, выражение для нужной функции от аргумента "x" малое и нужные пределы изменения аргумента вы можете не только задать константами, но и прочитать откуда-то (с той же консоли или из файла).

скриншот вывода консольного приложения
14.03.2015, 12:47 [44027 просмотров]
Черчение графика через C++ Visual Studio

Нужно начерить график к завтрашнему, а я не в зуб ногой
Есть ли материал в интернете, как чертить графики через C++ Visual Studio 2010? Гуглил, не нашёл.
Так бы на матлабе начертил б, но надо с экрана перед этим считать данные, а потом на основе их строить график
Лучшие ответы ( 1 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Построение графика c++ visual studio 2013
Здравствуйте, подскажите пожалуйста как сделать вот такой график создал 4 массива, high low open.
Простая графика в Visual Studio 2013
Как в Visual Studio 2013 подключить библиотеки для графики, чтоб просто рисовать и двигать круги .
Создание окна WinAPI в Visual Studio, графика и кнопки
собственно вопрос - как? конечно понимаю что можно и другие кнопочки потыкать, может там и проще.

Имеются ли отличия в компиляторах у сред разработки Visual Studio 2006 и Visual Studio 2015 ?
скажите а где найти среду 2006 года? или можно использовать 2015 год?
Как построить график в c visual studio
На этом шаге мы рассмотрим один из алгоритмов, используемых для рисования в форме .
В заключение покажем, как в форме можно рисовать графики. Вид формы графиками функций sin(x) и tan(x) показан на рисунке 1. Коды обработчиков кнопок (фрагменты h -файла приложения, выводящего графики фукнций) приведены ниже.
#pragma once namespace My126_1 < using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; //Объявление функций приложения //--sin(x)--------------------- //математические функции берутся из класса Math double fs(double x) < return(Math::Floor(Math::Sin(x))); > //--tan(x)--------------------- double ft(double x) < return(Math::Floor(Math::Tan(x))); > /// /// Сводка для Form1 /// public ref class Form1 : public System::Windows::Forms::Form < . . . . . >#pragma endregion //=====Обработчики кнопок вывода графиков функций =========== private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) < Color ^col = gcnew Color(); Pen ^pen = gcnew Pen (col->Red); //чтобы создать графический объект, надо получить ссылку на него, //выполнив метод CreateGraphics() компонента (формы) Graphics ^im = this->CreateGraphics(); //вывод графика функции с использованием DrawLine() im->Clear(col->White); //закрасить предыдущее графическое //изображение белым цветом float x1, y1, x2, y2; //текущие координаты в пикселях в форме x1 = 0; y1 = 0; //начальные координаты графика функции f(х) //вычисление функции y=f(x) в точках x1, x2, . x2 = x1; while ( x2 < this->Width && y2 < this->Height) < x2+=5; //следующая точка в пикселях по оси X y2 = fs(x2) * 100; // эта функция определена в начале модуля //(*100 - для увеличения амплитуды, чтобы //было нагляднее) if ( y2 < 0 ) y2*=-1; //чтобы выводить отрицательные значения im->DrawLine(pen, x1, y1, x2, y2); // вывод линии между 2-мя точками // точка 2 должна стать точкой 1, // а точкой 2 должна стать следующая текущая точка: x1 = x2; y1 = y2; continue; > > private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) < Color ^col = gcnew Color(); Pen ^pen = gcnew Pen (col->Red); //чтобы создать графический объект, надо получить ссылку на него, //выполнив метод CreateGraphics() компонента (формы) Graphics ^im = this->CreateGraphics(); //вывод графика функции с использованием DrawLine() im->Clear(col->White); //закрасить предыдущее графическое //изображение белым цветом float x1, y1, x2, y2; //текущие координаты в пикселях в форме x1 = 0; y1 = 0; //начальные координаты графика функции f(х) //вычисление функции y=f(x) в точках x1, x2, . x2 = x1; while ( x2 < this->Width && y2 < this->Height) < x2+=10; //следующая точка в пикселях по оси X y2 = ft(x2) * 50; // эта функция определена в начале модуля //(*50 - для увеличения амплитуды, //чтобы было нагляднее) if ( y2 < 0 ) y2*=-1; //чтобы выводить отрицательные значения im->DrawLine(pen, x1, y1, x2, y2); // вывод линии между 2-мя точками // точка 2 должна стать точкой 1, // а точкой 2 должна стать следующая текущая точка: x1 = x2; y1 = y2; continue; > > private: System::Void button3_Click(System::Object^ sender, System::EventArgs^ e) < this->Close(); //завершение приложения >
Архив проекта можно взять здесь.
Рис.1. Графики синусоиды и тангенсоиды, построенные в форме
- ::identifier - это идентификатор (возможно, глобальный);
- class-name::identifier - это идентификатор, относящийся к классу;
- namespace::identifier - это идентификатор, тносящийся к пространству имен.
При выводе графика любой функции мы применили метод DrawLine() класса Graphics . Но напрямую сформировать указатель на этот класс, чтобы воспользоваться его членами (в частности методом DrawLine() ), нельзя. Над сначала получить ссылку на этот графический объект через специальный метод формы, который называется CreateGraphics() .
Если написать оператор
Graphics ^im = this->CreateGraphics();
то получим желаемое (метод, по его определению, формирует ссылку на графический объект).
Теперь через определенную нами ссылку типа Graphics можем добраться до членов класса Graphics (в частности до необходимого нам метода DrawLine() , который рисует прямую линию между двумя точками). Рисование происходит с помощью специального механизма, находящегося в классе Pen (перо или ручка с пером). Чтобы добраться до этого механизма, надо объявить ссылку на этот класс, а потом через нее добраться до нужного нам члена класса.
Формирование ссылки на класс происходит не само по себе, а с помощью утилиты gcnew , запускающей специальную программу-конструктор класса, который, в свою очередь, создает в выделенной утилитой памяти экземпляр класса, чтобы с ним можно было работать. Конструктор всегда имеет то же имя, что и класс, для которого он создается, только это обычная функция, выполняющая определенные действия по инициализации членов-данньх класса (она придает им некоторые начальные значения).
Конструктор для класса Pen имеет один параметр (цвет), потому что перо должно рисовать линии определенным цветом. Следовательно, прежде чем задавать работу конструктору класса Pen , нам нужно как-то определиться с цветом, который потом следует задать в качестве параметра этому конструктору. Цвета находятся в специальном классе Color (цвет). Чтобы добраться до нужного цвета в этом классе, надо сформировать ссылку на этот класс, а потом уже через нее достать нужный цвет. Отсюда имеем:
Color^ col = gcnew Color();
Утилита gcnew запускает конструктор класса Color , формирует экземпляр класса в памяти и выдает ссылку на этот экземпляр в переменную col . Теперь любой цвет из Color можно достать через полученную ссылку так:
При этом откроется окно подсказчика, из которого остается только выбрать подходящий цвет. Когда вы начнете вводить начальные буквы нужного вам объекта, среда сразу установит подсветку на ближайший объект, имя которого начинается на вводимые вами символы, что ускоряет процесс выбора нужной строки. После выбора строки нажмите клавишу Enter и она попадет в ваш оператор. Если вы не нашли подходящую строку, значит в объекте, на который вы сформировали ссылку, такого члена-данного нет.
После определения цвета можно выполнять конструктор пера:
Pen^ pen = gcnew Pen (col->Red);
Чтобы график выводился на поле формы, не занятое предыдущим графиком, следует графический объект, которым мы пользуемся для рисования (он фактически задает специальный холст для рисования, состоящий из точек-пикселей), закрасить нейтральным цветом, на фоне которого будет выводиться новый график.
Чтобы рисовать график, из непрерывной функции получают в цикле дискретные значения ее точек и между двумя соседними точками проводят прямую линию. Естественно, чем больше точек на данной поверхности, тем более точным будет график.
Со следующего шага мы начнем знакомиться с компонентами, используемыми при создании интерфейса приложения .