Evgenii Legotckoi
Evgenii LegotckoiҚар. 30, 2015, 8:49 Т.Ж.

Qt/C++ - Сабақ 030. QCustomPlot - диаграммалармен жұмыс істеудің жылдам бастауы

Мен Qt ішіндегі диаграммалармен жұмыс істеуге қатысты QCustomPlot туралы үнемі естимін, бірақ алғашында мен велосипедтерімді қолданбаларымның бірінде жасадым, енді бос уақытымда осы кітапханамен танысуды жөн көрдім. Өйткені, әзірлеушілер үшін әлі де жұмыс істейтін нәрсе бар сияқты көрінді, бірақ қазіргі уақытта оның өте қуатты функционалдығы бар. Мен онымен қуана жұмыс істедім және еркелетуге және оқуға арналған кодымды сызып алдым.

Ал енді нүктеге жақынырақ. Мысалдағы бағдарлама келесі функцияларды орындауы керек:

  1. Бірнеше нүкте үшін бір график сызу;
  2. Тік жылжымалы сызық болуы;
  3. Тік сызықтан кейін тік сызықтан графикке ең жақын нүктелерде көтерілетін сызғыш келеді.

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 мысалы

Бейне оқулық

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

z
  • Қаң. 23, 2017, 6:30 Т.Ж.

А почему именно QCustomPlot а не QCharts?

Evgenii Legotckoi
  • Қаң. 23, 2017, 10:29 Т.Ж.

Потому, что на момент написания статьи QCharts был только в коммерческой платной версии.

М
  • Қаз. 20, 2017, 9:30 Т.Ж.

Здравствуйте. Скачал архив, работает. Создал проект и вставил код в 2 файла, ка вы указали - не работает.  В mainwindow.cpp выдает 3 ошибки:

C:\Qt\project\3\mainwindow.cpp:14: ошибка: 'class Ui::MainWindow' has no member named 'gridLayout'
ui->gridLayout->addWidget(wGraphic,1,0,1,1); // ... и устанавливаем
^
C:\Qt\project\3\mainwindow.cpp:30: ошибка: 'class QCustomPlot' has no member named 'addPlottable'
wGraphic->addPlottable(verticalLine);   // Добавляем линию РЅР° полотно
^
C:\Qt\project\3\mainwindow.cpp:91: ошибка: 'class Ui::MainWindow' has no member named 'lineEdit'
ui->lineEdit->setText("x: " + QString::number(tracer->position->key()) +
^
Скажите пожалуйста, как это исправить!
Evgenii Legotckoi
  • Қаз. 20, 2017, 9:40 Т.Ж.

ui->lineEdit и ui->gridLayout - это объекты, которые должны были быть созданы в графическом дизайнере. ui - это объект графического интерфейса. Их у вас просто нет, поработайте с графическим дизайнером, чтобы создать его.


что касается addPlotable, так это отсутсвует инклюд библиотеки, заголовочного файла в mainwindow.h
М
  • Қаз. 20, 2017, 9:43 Т.Ж.

Но почему вы это не описали? Не могли бы вы описать.


Evgenii Legotckoi
  • Қаз. 20, 2017, 10:03 Т.Ж.

Использование дизайнера в Qt Creator и использование ui файлов является распространённой практикой в Qt фреймворке.
Написать отдельную статью про то, что это такое? - может быть.
Описывать в каждой статье основы? - нет. Не о том статья.

A
  • Қаз. 23, 2017, 5:25 Т.Ж.

такая же ошибка с методом addPlottable. Инклуд проблему не решил.

Evgenii Legotckoi
  • Қаз. 23, 2017, 5:55 Т.Ж.

Куда инклюд писали?

A
  • Қаз. 23, 2017, 5:57 Т.Ж.

Прописал в заголовочном файле mainwindow.h

Может версия другая? У меня в файле библиотеки вообще нет такого метода.
Evgenii Legotckoi
  • Қаз. 23, 2017, 6:03 Т.Ж.

То есть вы использовали последнюю версию библиотеки с сайта разработчика QCustomPlot?
Да, вы правы.. я посмотрел документацию у разработчика библиотеки. Он выпустил новую версию. И там отсутсвует данный метод.
Там сейчас делатся через QCPGraph, через установку данных через его метод data()

customPlot->graph()->data()->set(timeData);
A
  • Қаз. 23, 2017, 6:09 Т.Ж.

Спасибо за информацию, а как же теперь пользоваться QCPCurve и другими типами? Краб то заполнить могу информацией, а как добавить её на customPlot?

Evgenii Legotckoi
  • Қаз. 23, 2017, 6:11 Т.Ж.
Краб то заполнить могу информацией
В смысле QCPGraph ?

QCustomPlot имеет метод addGraph
A
  • Қаз. 23, 2017, 6:15 Т.Ж.

Меня интересует именно параметрические кривые, я могу их строить с помощью QCPTGraph, но их отображение имеет отклонения(разрывы в функции, неточности). Я полагал QCPCurve сможет решить эту проблему, но как видите из за отсутствия метода addPlottable не могу сообразить как кривую добавить на график.

A
  • Қаз. 23, 2017, 6:16 Т.Ж.

Или может скачать старую версию библиотеки? Вы не могли бы скинуть файлы старой библиотеки мне на почту?

Evgenii Legotckoi
  • Қаз. 23, 2017, 6:20 Т.Ж.

Ну параметрические кривые могу быть вполне отображены и новой библиотекой, на оф. сайте есть пара примеров параметрических кривых.

А что касается бибилотеки, то скачайте проект из этой статьи . Там в составе проетк есть старая библиотека. Ссылка перед видео.
A
  • Қаз. 23, 2017, 6:25 Т.Ж.

Спасибо, разберёмся)

h
  • Мамыр 30, 2018, 9:14 Т.Қ.

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.

Docent
  • Қаң. 21, 2020, 2:12 Т.Қ.

Полезная статья. Как всегда - то что надо.
Добавлю ещё маленькую полезность - после установки tracer (88 строка) и перед выводом значений в lineEdit (91 строка) стоит добавить updatePosition иначе будут отображаться значения из предыдущей позиции.

Docent
  • Жел. 25, 2020, 2:36 Т.Ж.

Доброго времени, это снова я) Имеется ли возможность подключения одного QCPItemTracer ко многим QCPGraph ?
Например у нас на одном QCustomPlot создано множество QCPGraph, делать для каждого их них по одному QCPItemTracer совсем неудобно и громоздко (фильтр для проверки к какому QCPGraph ближе оказался tracer и отключение видимости всех остальных... ну так себе), создание +1 невидимого QCPGraph содержащего в себе данные всех предыдущих - накладно (сотни тысяч точек в каждом). Отсюда и возник вопрос - как используя один QCPItemTracer перемещаться по всем QCPGraph.


(на изображении небольшой пример, tracer остался где-то далеко на 1м graph())

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз