Мен Qt ішіндегі диаграммалармен жұмыс істеуге қатысты QCustomPlot туралы үнемі естимін, бірақ алғашында мен велосипедтерімді қолданбаларымның бірінде жасадым, енді бос уақытымда осы кітапханамен танысуды жөн көрдім. Өйткені, әзірлеушілер үшін әлі де жұмыс істейтін нәрсе бар сияқты көрінді, бірақ қазіргі уақытта оның өте қуатты функционалдығы бар. Мен онымен қуана жұмыс істедім және еркелетуге және оқуға арналған кодымды сызып алдым.
Ал енді нүктеге жақынырақ. Мысалдағы бағдарлама келесі функцияларды орындауы керек:
- Бірнеше нүкте үшін бір график сызу;
- Тік жылжымалы сызық болуы;
- Тік сызықтан кейін тік сызықтан графикке ең жақын нүктелерде көтерілетін сызғыш келеді.
QCustomPlot үшін жоба құрылымы
Жоба құрылымы келесі файлдарды қамтиды:
- QCustomPlotExample.pro - профильдік жоба;
- mainwindow.h - қолданбаның негізгі терезесінің тақырып файлы;
- mainwindow.cpp - қолданбаның негізгі терезесі үшін бастапқы код файлы;
- main.cpp - қолданбаның негізгі бастапқы файлы;
- qcustomplot.h - QCustomPlot кітапханасының тақырып файлы;
- qcustomplot.cpp - бастапқы код файлы QCustomPlot.
Мен кітапхана файлдарының тізімін бермеймін, олар өте үлкен және біз оларға кірмейміз, біз тек жобаға файлдарды қосамыз және тақырып файлын MainWindow. класына қосамыз.
mainwindow.h
MainWindow класының тақырып файлында біз QCustomPlot кітапханасын қосамыз, сонымен қатар кенептің өзін, тік сызықты QCPCurve сыныбының объектісі ретінде және бақылаушыны жариялаймыз. 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 тінтуірді басу және жылжыту сигналдарын шығара алады және қалыпты жағдайда ол әрқашан тінтуірдің өз үстінен қозғалуына себеп болады, сондықтан кенептің мазмұнын қайта салу үшін тінтуір түймешігі басылғанын тексеру қажет. Егер тінтуірдің түймесі басылса, онда тік сызықты жылжытамыз, ал lineEdit өрісінде оның орналасқан жерінің координаттарын бере отырып, тресер одан кейін секіреді. Яғни, қазіргі уақытта ол графиктің қай нүктесінде орнатылған. Трекер диаграмманың барлық нүктелері арқылы емес, тек QVector арқылы жүктелген пункттер арқылы өтетінін ескертемін.
Қолданба терезесінде QCustomPlot нысанын орнату IDE QtCreator графикалық дизайнері арқылы емес, қолданбаның бастапқы кодында орындалады.
#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); }
Барлығы
Орындалған жұмыстың нәтижесінде сіз келесі суретте көрсетілгендей болатын өтініш аласыз. Сондай-ақ, қосымшаның демонстрациясын бейне оқулықтан көруге болады.
Жобаны zip мұрағатында жүктеп алу сілтемесі: QCustomPlot мысалы
А почему именно 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())