Ich höre ständig von QCustomPlot bezüglich der Arbeit mit Graphen in Qt , aber zuerst habe ich meine Fahrräder in einer meiner Anwendungen erstellt, und jetzt habe ich beschlossen, diese Bibliothek in meiner freien Minute kennenzulernen. Es schien, dass es für die Entwickler noch etwas zu tun hat, aber im Moment verfügt es über sehr leistungsstarke Funktionen. Ich habe es genossen, mit ihr zusammenzuarbeiten und meinen Code zum Verwöhnen und Lernen aufgeschrieben.
Kommen wir nun zum Punkt. Das Beispielprogramm sollte die folgenden Funktionen ausführen:
- Zeichnen Sie ein Diagramm mit mehreren Punkten;
- Eine vertikale bewegliche Linie haben;
- Der vertikalen Linie folgt der Tracer, der sich von der vertikalen Linie am nächsten zum Punkt des Diagramms befindet.
Projektstruktur für QCustomPlot
Die Projektstruktur umfasst die folgenden Dateien:
- QCustomPlotExample.pro - Projektprofil;
- mainwindow.h - Header-Datei des Hauptanwendungsfensters;
- mainwindow.cpp - Datei mit Quellcodes des Hauptfensters der Anwendung;
- main.cpp - Quellcodedatei der Hauptanwendung;
- qcustomplot.h - Header-Datei der Bibliothek QCustomPlot;
- qcustomplot.cpp - Quellcodedatei QCustomPlot
Ich werde keine Auflistungen von Bibliotheksdateien geben, sie sind sehr groß und wir steigen nicht darauf ein, wir fügen dem Projekt nur Dateien hinzu und fügen die Header-Datei in die MainWindow Klasse ein
mainwindow.h
In der Header-Datei der MainWindow -Klasse binden wir die QCustomPlot -Bibliothek, ein und deklarieren auch den Canvas selbst, die vertikale Linie als Objekt der QCPCurve -Klasse und den Tracer* * QCPItemTracer
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <qcustomplot.h> #include <QDebug> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; QCustomPlot *wGraphic; // Объявляем объект QCustomPlot QCPCurve *verticalLine; // Объявляем объект для вертикальной линии QCPItemTracer *tracer; // Трасировщик по точкам графика private slots: void slotMousePress(QMouseEvent * event); void slotMouseMove(QMouseEvent * event); }; #endif // MAINWINDOW_H
mainwindow.cpp
QCustomPlot kann Signale zum Klicken und Bewegen der Maus geben und löst unter normalen Bedingungen immer ein Signal zum Bewegen der Maus über sich selbst aus. Sie müssen also überprüfen, ob die Maustaste gedrückt wird, um den Inhalt der Leinwand neu zu zeichnen. Für den Fall, dass die Maustaste gedrückt wird, verschieben wir die vertikale Linie, und der Tracer springt dahinter und gibt die Koordinaten seiner Position im Feld lineEdit an. Das heißt, an welcher Stelle des Diagramms es derzeit installiert ist. Beachten Sie, dass der Tracer nicht alle Punkte des Diagramms durchläuft, sondern nur diejenigen, die mit QVector geladen wurden.
Das Objekt QCustomPlot wird im Anwendungsfenster nicht über den Grafikdesigner IDE QtCreator installiert, sondern im Quellcode der Anwendung.
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QApplication> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // this->setGeometry(300,100,640,480); // Инициализируем объект полотна для графика ... wGraphic = new QCustomPlot(); ui->gridLayout->addWidget(wGraphic,1,0,1,1); // ... и устанавливаем // Инициализируем вертикальную линию verticalLine = new QCPCurve(wGraphic->xAxis, wGraphic->yAxis); // Подключаем сигналы событий мыши от полотна графика к слотам для их обработки connect(wGraphic, &QCustomPlot::mousePress, this, &MainWindow::slotMousePress); connect(wGraphic, &QCustomPlot::mouseMove, this, &MainWindow::slotMouseMove); // создаём вектора для вертикальной линии QVector<double> x(2) , y(2); x[0] = 0; y[0] = -50; x[1] = 0; y[1] = 50; wGraphic->addPlottable(verticalLine); // Добавляем линию на полотно verticalLine->setName("Vertical"); // Устанавливаем ей наименование verticalLine->setData(x, y); // И устанавливаем координаты // создаём вектора для графика QVector<double> x1(5) , y1(5); x1[0] = -45; y1[0] = -43; x1[1] = 46; y1[1] = 42; x1[2] = -25; y1[2] = -24; x1[3] = -12; y1[3] = 10; x1[4] = 25; y1[4] = 26; // Добавляем график на полотно wGraphic->addGraph(wGraphic->xAxis, wGraphic->yAxis); wGraphic->graph(0)->setData(x1,y1); // Устанавливаем координаты точек графика // Инициализируем трассировщик tracer = new QCPItemTracer(wGraphic); tracer->setGraph(wGraphic->graph(0)); // Трассировщик будет работать с графиком // Подписываем оси координат wGraphic->xAxis->setLabel("x"); wGraphic->yAxis->setLabel("y"); // Устанавливаем максимальные и минимальные значения координат wGraphic->xAxis->setRange(-50,50); wGraphic->yAxis->setRange(-50,50); // Отрисовываем содержимое полотна wGraphic->replot(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::slotMousePress(QMouseEvent *event) { // Определяем координату X на графике, где был произведён клик мышью double coordX = wGraphic->xAxis->pixelToCoord(event->pos().x()); // Подготавливаем координаты по оси X для переноса вертикальной линии QVector<double> x(2), y(2); x[0] = coordX; y[0] = -50; x[1] = coordX; y[1] = 50; // Устанавливаем новые координаты verticalLine->setData(x, y); // По координате X клика мыши определим ближайшие координаты для трассировщика tracer->setGraphKey(coordX); // Выводим координаты точки графика, где установился трассировщик, в lineEdit ui->lineEdit->setText("x: " + QString::number(tracer->position->key()) + " y: " + QString::number(tracer->position->value())); wGraphic->replot(); // Перерисовываем содержимое полотна графика } void MainWindow::slotMouseMove(QMouseEvent *event) { /* Если при передвижении мыши, ей кнопки нажаты, * то вызываем отработку координат мыши * через слот клика * */ if(QApplication::mouseButtons()) slotMousePress(event); }
Ergebnis
Als Ergebnis der geleisteten Arbeit erhalten Sie einen Antrag, der wie in der folgenden Abbildung dargestellt aussieht. Eine Demonstration der Anwendung können Sie auch im Video-Tutorial sehen.
Link zum Download des Projekts in einem Zip-Archiv: QCustomPlot Example
А почему именно QCustomPlot а не QCharts?
Потому, что на момент написания статьи QCharts был только в коммерческой платной версии.
Здравствуйте. Скачал архив, работает. Создал проект и вставил код в 2 файла, ка вы указали - не работает. В mainwindow.cpp выдает 3 ошибки:
ui->lineEdit и ui->gridLayout - это объекты, которые должны были быть созданы в графическом дизайнере. ui - это объект графического интерфейса. Их у вас просто нет, поработайте с графическим дизайнером, чтобы создать его.
Но почему вы это не описали? Не могли бы вы описать.
Использование дизайнера в Qt Creator и использование ui файлов является распространённой практикой в Qt фреймворке.
Написать отдельную статью про то, что это такое? - может быть.
Описывать в каждой статье основы? - нет. Не о том статья.
такая же ошибка с методом addPlottable. Инклуд проблему не решил.
Куда инклюд писали?
Прописал в заголовочном файле mainwindow.h
То есть вы использовали последнюю версию библиотеки с сайта разработчика QCustomPlot?
Да, вы правы.. я посмотрел документацию у разработчика библиотеки. Он выпустил новую версию. И там отсутсвует данный метод.
Там сейчас делатся через QCPGraph, через установку данных через его метод data()
Спасибо за информацию, а как же теперь пользоваться QCPCurve и другими типами? Краб то заполнить могу информацией, а как добавить её на customPlot?
Меня интересует именно параметрические кривые, я могу их строить с помощью QCPTGraph, но их отображение имеет отклонения(разрывы в функции, неточности). Я полагал QCPCurve сможет решить эту проблему, но как видите из за отсутствия метода addPlottable не могу сообразить как кривую добавить на график.
Или может скачать старую версию библиотеки? Вы не могли бы скинуть файлы старой библиотеки мне на почту?
Ну параметрические кривые могу быть вполне отображены и новой библиотекой, на оф. сайте есть пара примеров параметрических кривых.
Спасибо, разберёмся)
Here the tracer is moving by Mouse Press And Mouse Move.How to move the Tracer by using the QTimer.The tracer has to be move from origin to end point automatically/programically by using QTimer.
Полезная статья. Как всегда - то что надо.
Добавлю ещё маленькую полезность - после установки tracer (88 строка) и перед выводом значений в lineEdit (91 строка) стоит добавить updatePosition иначе будут отображаться значения из предыдущей позиции.
Доброго времени, это снова я) Имеется ли возможность подключения одного QCPItemTracer ко многим QCPGraph ?
Например у нас на одном QCustomPlot создано множество QCPGraph, делать для каждого их них по одному QCPItemTracer совсем неудобно и громоздко (фильтр для проверки к какому QCPGraph ближе оказался tracer и отключение видимости всех остальных... ну так себе), создание +1 невидимого QCPGraph содержащего в себе данные всех предыдущих - накладно (сотни тысяч точек в каждом). Отсюда и возник вопрос - как используя один QCPItemTracer перемещаться по всем QCPGraph.
(на изображении небольшой пример, tracer остался где-то далеко на 1м graph())