На этом шаге мы рассмотрим построение нескольких графиков.
Рассмотрим пример построения построения 2-х графиков в одном компоненте Chart.
Возьмем классический пример построения графиков функций y=sin(x) и y=cos(x) на заданном промежутке. Внешний вид формы на этапе разработки приведен на рисунке 1.
Рис.1. Внешний вид формы на этапе разработки
Как видно из рисунка 1, мы убрали все домонстрационные данные с компонента. Для этого воспользовались коллекцией Series и в открывшемся окне редактора выделили серию и нажали кнопку Удалить.
Понятно, что все расчеты и построение выполняется в обработчике кнопки Построить графики. Приведем текст этого обработчика, с потом прокомментируем некоторые особо интересные, на наш взгляд, моменты.
// Построение графиков private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { // Левая граница графика double XMin = Convert::ToDouble(textBox1->Text); // Правая граница графика double XMax = Convert::ToDouble(textBox2->Text); // Шаг графика double Step = Convert::ToDouble(textBox3->Text); // Количество точек графика int count = (int)Math::Ceiling((XMax - XMin) / Step) + 1; // Создаём два словаря для размещения данных Dictionary <double, double> f1 = gcnew Dictionary<double, double>(); Dictionary <double, double> f2 = gcnew Dictionary<double, double>(); // Расчитываем точки для графиков функции for (double x = XMin; x <= XMax; x += Step) { f1.Add(x, (Math::Sin(x))); f2.Add(x, (Math::Cos(x))); } // Создаём новую область для построения графика ChartArea^ area = gcnew ChartArea(); // Даём ей имя (чтобы потом добавлять графики) area->Name = "myGraph"; // Задаём левую и правую границы оси X area->AxisX->Minimum = XMin; area->AxisX->Maximum = XMax; // Задаём нижнюю и верхнюю границы оси Y area->AxisY->Minimum = -1.0; area->AxisY->Maximum = 1.0; area->AxisY->Interval = 0.5; // Определяем шаг сетки area->AxisX->MajorGrid->Interval = Step; // Отображение промежуточных линий // area->AxisX->MinorGrid->Enabled = true; area->AxisY->MinorGrid->Enabled = true; // Position указывает (в процентах) положение и // размер графика относительно родительского контрола area->Position->X = 3; area->Position->Y = 1; area->Position->Height = 90; area->Position->Width = 75; // Добавляем область в диаграмму chart1->ChartAreas->Add(area); // Создаём объект для первого графика Series^ series1 = gcnew Series(); // Ссылаемся на область для построения графика series1->ChartArea = "myGraph"; // Задаём тип графика - сплайны series1->ChartType = SeriesChartType::Spline; // Указываем ширину линии графика series1->BorderWidth = 3; // Название графика для отображения в легенде series1->LegendText = "y=sin(x)"; // Добавляем в список графиков диаграммы chart1->Series->Add(series1); // Аналогичные действия для второго графика Series^ series2 = gcnew Series(); series2->ChartArea = "myGraph"; series2->ChartType = SeriesChartType::Spline; series2->BorderWidth = 3; series2->LegendText = "y=cos(x)"; chart1->Series->Add(series2); // Создаём легенду, которая будет показывать названия Legend^ legend = gcnew Legend(); chart1->Legends->Add(legend); // Добавляем вычисленные значения в графики chart1->Series[0]->Points->DataBindXY(f1.Keys, f1.Values); chart1->Series[1]->Points->DataBindXY(f2.Keys, f2.Values); }
Результат работы приложения приведен на рисунке 2.
Рис.2. Результат работы приложения
Прокомментируем интересные моменты приведенного обработчика.
Понятно, что сначала читаются введенные параметры, определяющие левую, правую границы и шаг изменения аргумента. В строке
// Количество точек графика int count = (int)Math::Ceiling((XMax - XMin) / Step) + 1;
Данные, используемые для построения графика, вы решили хранить в словарях, поэтому в строках:
// Создаём два словаря для размещения данных Dictionary <double, double> f1 = gcnew Dictionary<double, double>(); Dictionary <double, double> f2 = gcnew Dictionary<double, double>(); // Расчитываем точки для графиков функции for (double x = XMin; x <= XMax; x += Step) { f1.Add(x, (Math::Sin(x))); f2.Add(x, (Math::Cos(x))); }
После создания области для построения графика и придания ей имени:
// Создаём новую область для построения графика ChartArea^ area = gcnew ChartArea(); // Даём ей имя (чтобы потом добавлять графики) area->Name = "myGraph";
// Задаём левую и правую границы оси X area->AxisX->Minimum = XMin; area->AxisX->Maximum = XMax; // Задаём нижнюю и верхнюю границы оси Y area->AxisY->Minimum = -1.0; area->AxisY->Maximum = 1.0; area->AxisY->Interval = 0.5; // Определяем шаг сетки area->AxisX->MajorGrid->Interval = Step;
Далее мы отображаем промежуточные линии (свойство MinorGrid, а свойство MajorGrid используется для задания параметров основных линий) только по оси Y.
// Отображение промежуточных линий // area->AxisX->MinorGrid->Enabled = true; area->AxisY->MinorGrid->Enabled = true;
При построении графика долго не удавалось разместить его во всю ширину компонента Chart, пока мы не воспользовались свойством Position области построения. Его подсвойства X, Y определяют координаты верхнего левого угла области построения графика относительно компонента Chart, а значения свойств Height и Width определяют (в процентах) область, которую будет занимать график:
// размер графика относительно родительского контрола
area->Position->X = 3;
area->Position->Y = 1;
area->Position->Height = 90;
area->Position->Width = 75;
Остальные действия не вызовут вопросов. Единственное, на что следует обратить внимание, это добавление легенды на график: сначала легенда определяется через свойство LegendText каждой серии, а потом создается объект легенты, который добавляется методом Add() в свойство Legends компонента Chart.
Последние две строки:
chart1->Series[0]->Points->DataBindXY(f1.Keys, f1.Values); chart1->Series[1]->Points->DataBindXY(f2.Keys, f2.Values);
На следующем шаге мы продолжим изучение этого вопроса.