Chart, примеры в Studio
Компонента Chart (диаграмма) в Visual Studio довольно удобна, хотя для начинающих обычно сложно выбрать из множества её возможностей самые актуальные. К тому же, задокументировано-то всё лишь на MSDN.
Приведу несколько примеров, анализ которых поможет Вам быстро освоить основные приёмы работы с графиками и диаграммами в Visual C++. Все коды проверены в сборке Express 2010.
Пример 1. Добавим на форму компоненту Chart и выведем туда данные
//По нажатию кнопки 1 используем заранее добавленную компоненту Chart using namespace System::Collections::Generic; using namespace System::Drawing::Drawing2D; using namespace System::Drawing; Dictionary <double, double> f1 = gcnew Dictionary<double, double>(); ArrayList points = gcnew ArrayList(); Pen ^pen = gcnew Pen(System::Drawing::Color::Red); //создаем перо SolidBrush ^peen = gcnew SolidBrush(System::Drawing::Color::Green); //создаем кисть double x0=0,xmax=Math::PI,dx=Math::PI/100.; //границы графика по оси x и шаг f1.Clear(); using namespace System::Windows::Forms::DataVisualization::Charting; chart1->Series[0]->ChartType = SeriesChartType::Line; chart1->Series[0]->MarkerStyle = MarkerStyle::Circle; for (double x = x0; x <= xmax; x += dx) f1.Add((int)(x*100)/100., (Math::Sin(x))); chart1->Series[0]->Points->DataBindXY(f1.Keys, f1.Values); chart1->Series[0]->LegendText = L"функция"; chart1->Series[0]->Color = System::Drawing::Color::Green; chart1->Series[0]->BorderWidth = 2;
Пример 2. Сделаем красивый Chart программно, можно по нажатию новой кнопки на той же форме
using namespace System; using namespace System::Windows::Forms; using namespace System::Drawing; using namespace System::Windows::Forms::DataVisualization::Charting; //Общие свойства Chart ^myChart = gcnew Chart(); myChart->Parent = this; myChart->Left = 10; myChart->Top = 10; myChart->Width = (this->ClientSize.Width - 10); myChart->Height =(this->ClientSize.Height - 20); myChart->BringToFront(); //или chart1->Visible = false; ChartArea ^myChartArea = gcnew ChartArea(); //Область в которой будет построен график (их может быть несколько) myChartArea->Name = "myChartArea"; myChart->ChartAreas->Add(myChartArea); // График (их может быть несколько) Series ^mySeries1 = gcnew Series(); mySeries1->ChartType = SeriesChartType::Column; mySeries1->ChartArea = "myChartArea"; myChart->Series->Add(mySeries1); // Исходные данные для графика array <double> ^yval1 = { 10, 6, 4, 6, 3 }; array <System::String ^> ^xval = { "Январь", "Февраль", "Март", "Апрель", "Май" }; mySeries1->Points->DataBindXY(xval, yval1); //фон градиентом myChart->BackColor = System::Drawing::Color::MistyRose; myChart->BackGradientStyle = GradientStyle::DiagonalLeft; //границы в современном стиле myChart->BorderSkin->SkinStyle = BorderSkinStyle::Sunken; myChart->BorderSkin->PageColor = this->BackColor; //линии сетки покажем разными цветами myChartArea->AxisX->MajorGrid->LineColor = System::Drawing::SystemColors::ControlDark; myChartArea->AxisY->MajorGrid->LineColor = System::Drawing::SystemColors::ControlLight; //добавим второй график Series ^mySeries2 = gcnew Series(); mySeries2->ChartType = SeriesChartType::Point; mySeries2->ChartArea = "myChartArea"; myChart->Series->Add(mySeries2); array <double> ^yval2 = { 4, 7, 3, 5, 5 }; mySeries2->Points->DataBindXY(xval, yval2);
Вот что вышло:
Создаем программно красивый Chart в проекте C++ Windows Forms
Пример 3. Вытащим данные из Chart в TextBox
textBox1->Clear(); for each (DataPoint ^p in myChart->Series[0]->Points) { // Пробегаю по всем точкам первой кривой в графике textBox1->AppendText("X=" + p->XValue.ToString()+" "); for each (double yp in p->YValues) //Y является массивом, поэтому пробегаю по массиву textBox1->AppendText("Y=" + yp.ToString()); textBox1->AppendText(System::Environment::NewLine); }
Пример 4. Сделаем парсер выражений на основе чужого класса - это можно применить для создания полноценного "графопостроителя"
Добавим какой-нибудь не очень сложный парсер, например, класс parser.cpp от Chaos Master.
Кинем файлы parser.cpp
и parser.h
в папку с кодом (Имя_проекта/Имя_проекта, где находится Form1.h
). В меню скажем Проект - Существующий элемент и добавим файл .cpp (он д.б. в "Файлы исходного кода" Обозревателя решений)
Код выбранного нами парсера старый, так что нам придётся кое-что переделывать, например, строки char *
в String ^
и обратно.
Добавим на форму компоненты textBox1
и label1
, напишем демо-код для применения парсера (вызывается по нажатию кнопки):
TParser *parser = new TParser(); try { String ^Str=textBox1->Text; double x=0; //а можно ведь в цикле взять очередную переменную откуда-то! Str=Str->Replace("x",x.ToString()); using namespace Runtime::InteropServices; char *p = (char*) (Marshal::StringToHGlobalAnsi (Str)).ToPointer (); parser->Compile(p); parser->Evaluate(); label1->Text= parser->GetResult().ToString(); } catch(TError error) { System::String ^ str1 = gcnew System::String (error.error); System::String ^ str2 = gcnew System::String (error.pos.ToString()); label1->Text= "Error " + str1 + " at position " + str2; return; }
Возможно, понадобится изменить какие-то ещё мелочи, например, я в файле
parser.cpp
раскомментарил строку//#include "stdafx.h"и изменил в коде
exp(1)
наexp(1.)
- иначе не компилировалось в Studio.Также ясно, что в начале файла
form1.h
добавлена строка#include "parser.h"
Теперь в поле ввода можно писать любые допустимые парсером выражения с переменной x
, например, cos(x)+1
, текущее значение переменной x
из программы подставится в выражение и его результат динамически подсчитается.
На основе показанных кодов легко сделать, например, программу построения графиков с интерпретацией введённой пользователем функции. Скажем, если выражение для функции с аргументом, обозначенным x
, вводится в текстовое поле textBox1
, код построения графика функции в пределах от 0
до 3.14
с шагом, равным 0.1
, будет таким:
TParser *parser = new TParser(); try { using namespace Runtime::InteropServices; using namespace System::Collections::Generic; using namespace System::Drawing::Drawing2D; using namespace System::Drawing; using namespace System::Windows::Forms::DataVisualization::Charting; Dictionary <double, double> f1 = gcnew Dictionary<double, double>(); chart1->Series[0]->ChartType = SeriesChartType::Line; chart1->Series[0]->MarkerStyle = MarkerStyle::Circle; for (double x=0; x<3.14; x+=0.1) { String ^Str=textBox1->Text; Str=Str->Replace("x",x.ToString()); Str=Str->Replace(",","."); //Если не та локаль //А лучше извлечь через Single::TryParse независимо от локали char *p = (char*) (Marshal::StringToHGlobalAnsi (Str)).ToPointer (); parser->Compile(p); parser->Evaluate(); f1.Add(x, parser->GetResult()); } chart1->Series[0]->Points->DataBindXY(f1.Keys, f1.Values); chart1->Series[0]->LegendText = textBox1->Text; chart1->Series[0]->Color = System::Drawing::Color::Green; chart1->Series[0]->BorderWidth = 2; } catch (TError error) { System::String ^ str1 = gcnew System::String (error.error); System::String ^ str2 = gcnew System::String (error.pos.ToString()); MessageBox::Show( "Error " + str1 + " at position " + str2); return; }
P.S. В более новой Studio 2019 пришлось сделать ^f1
вместо f1
и, соответственно, везде f1->
вместо f1.
Заменить фиксированные пределы и шаг на вводимые из формы - элементарно. Вот что вышло для теста:
Пример построения графика на основе парсера функций
Пример 5. Применение разрывов
На форму проекта помещена chart1
со свойством Dock = Fill
, построение происходит по загрузке формы.
private: System::Void MyForm_Load(System::Object^ sender, System::EventArgs^ e) { using namespace System::Collections::Generic; using namespace System::Drawing::Drawing2D; using namespace System::Windows::Forms::DataVisualization::Charting; Dictionary <double, double> ^f1 = gcnew Dictionary<double, double>(); chart1->Series[0]->ChartType = SeriesChartType::Line; chart1->Series[0]->MarkerStyle = MarkerStyle::Circle; chart1->ChartAreas[0]->AxisY->ScaleBreakStyle->Enabled = true; chart1->ChartAreas[0]->AxisY->ScaleBreakStyle->CollapsibleSpaceThreshold = 25; chart1->ChartAreas[0]->AxisY->ScaleBreakStyle->LineWidth = 2; chart1->ChartAreas[0]->AxisY->ScaleBreakStyle->LineColor = Color::Red; chart1->ChartAreas[0]->AxisY->ScaleBreakStyle->StartFromZero = StartFromZero::Auto; chart1->ChartAreas[0]->AxisY->ScaleBreakStyle->Spacing = 2; for (double x = 0; x < 3.14; x += 0.1) { double f = tan(x); //#include <cmath> f1->Add(x, f); } chart1->Series[0]->Points->DataBindXY(f1->Keys, f1->Values); chart1->Series[0]->LegendText = L"tan(x)"; chart1->Series[0]->Color = System::Drawing::Color::Green; chart1->Series[0]->BorderWidth = 2; }
разрывы по оси y на графике
04.02.2014, 17:03 [53311 просмотров]