Qwt и Qt Creator. Часть 3: график как элемент Designer Form

от автора

В примерах использованы Qt Creator 3.0.0 (MinGW) и Qwt-6.1.0.

Для понимания этой статьи читатель должен иметь начальный опыт разработки windows-приложений в среде Qt Creator, понимать концепцию «сигнал-слот». Также рекомендуется познакомиться с частью №1 и №2 цикла моих статей про Qwt: habrahabr.ru/post/211204/
habrahabr.ru/post/211867/

Qwt – графическая библиотека, позволяющая значительно упростить процесс визуализации данных в программе. Упрощение заключается в следующем: нет необходимости вручную прописывать элементы отображения, такие как шкалы координат, сетки, кривые данных и проч. Следует лишь задавать параметры этих элементов.

В предыдущих частях цикла статей элементы управления графиком добавлялись ручным кодированием. Думаю, большинство программистов предпочли бы пользоваться средствами
Qt Creator. В части №3 мы сделаем следующее:

• добавим виджет для отображения графика в Designer Form, что позволит использовать элементы управления Qt Creator;
• построим демонстрационную кривую, реализуем базовые удобства работы с графиком: возможность перемещения по полю графика, его приближение/удаление, отобразим координаты курсора при его перемещении;
• отобразим координат клика в строке состояния Designer Form;
• переместим кривую вдоль оси х, используя стандартные элементы управления из Qt Creator.

Содержание этой статьи в некоторой степени дублирует содержание части №2. Это сделано специально, так как хотелось сделать статьи независимыми друг от друга.

Добавим виджет для отображения графика в Designer Form

1. Создаем проект с Mainwindow. Напомню обязательную процедуру для использования Qwt: добавить строчку «CONFIG += qwt» в файл .pro проекта и запустить qmake через контекстное меню (правой кнопкой мыши на корневую папку проекта).

2. Открываем редактор формы и находим виджет «Widget». Размещаем его на форме.

3. Изменяем имя добавленного «Widget» на «Qwt_Widget».
4. Правой кнопкой щелкаем на «Qwt_Widget» и выбираем «Promote to…»

5. В поле Promoted class name печатаем «QwtPlot». В поле Header file меняем «qwtplot.h» на «qwt_plot.h». Нажимаем Add и закрываем окно.

Построим демонстрационную кривую, реализуем базовые удобства работы с графиком

Ниже приведен код, во многом аналогичный опубликованному в части №2. Код немного улучшен, удалены фрагменты, отвечающие за «ручное» добавление элементов управления.
Обратите особое внимание на следующее. Раньше мы создавали приватную переменную QwtPlot *d_plot, а затем использовали такую конструкцию, как, например:

d_plot->setTitle( "Qwt demonstration" );  

Теперь для настроек свойств графика мы будем использовать следующую конструкцию:

ui->Qwt_Widget->setTitle( "Qwt demonstration" ); 

Причем, если в коде отсутствуют такие конструкции, то «Qwt_Widget» является пустым. После добавления строчки с настройкой этот виджет начинает отображать поле графика.

Содержание файла mainwindow.h

#ifndef MAINWINDOW_H #define MAINWINDOW_H  #include <QMainWindow>  #include <qwt_plot.h> #include <qwt_plot_grid.h>  #include <qwt_legend.h>  #include <qwt_plot_curve.h> #include <qwt_symbol.h>  #include <qwt_plot_magnifier.h>  #include <qwt_plot_panner.h>  #include <qwt_plot_picker.h>  #include <qwt_picker_machine.h> namespace Ui { class MainWindow; }  class MainWindow : public QMainWindow {     Q_OBJECT  public:     explicit MainWindow(QWidget *parent = 0);     ~MainWindow();  private Q_SLOTS:     void click_on_canvas( const QPoint &pos );  private:      Ui::MainWindow *ui;      void addPlot();     void addPlotGrid();      QwtPlotCurve *curve;     QPolygonF points;     void addCurve();      void enableMagnifier();     void enableMovingOnPlot();      void enablePicker(); };  #endif // MAINWINDOW_H 

Содержание файла mainwindow.cpp

#include "mainwindow.h" #include "ui_mainwindow.h"   MainWindow::MainWindow(QWidget *parent) :     QMainWindow(parent),     ui(new Ui::MainWindow) {     ui->setupUi(this);      // Создать поле со шкалами для отображения графика     addPlot();      // Включить масштабную сетку     addPlotGrid();      // Кривая     addCurve();      // Включить возможность приближения/удаления графика     enableMagnifier();      // Включить возможность перемещения по графику     enableMovingOnPlot();      // Включить отображение координат курсора и двух перпендикулярных     // линий в месте его отображения     enablePicker();  }  MainWindow::~MainWindow() {     delete ui; }  void MainWindow::addPlot() {     // #include <qwt_plot.h>     ui->Qwt_Widget->setTitle( "Qwt demonstration" );     ui->Qwt_Widget->setCanvasBackground( Qt::white );      // Параметры осей координат     ui->Qwt_Widget->setAxisTitle(QwtPlot::yLeft, "Y");     ui->Qwt_Widget->setAxisTitle(QwtPlot::xBottom, "X");     ui->Qwt_Widget->insertLegend( new QwtLegend() );  }  void MainWindow::addPlotGrid() {     // #include <qwt_plot_grid.h>     QwtPlotGrid *grid = new QwtPlotGrid();     grid->setMajorPen(QPen( Qt::gray, 2 )); // цвет линий и толщина     grid->attach( ui->Qwt_Widget ); }  void MainWindow::addCurve() {     //#include <qwt_plot_curve.h>     curve = new QwtPlotCurve();     curve->setTitle( "Demo Curve" );     curve->setPen( Qt::blue, 6 ); // цвет и толщина кривой      // Маркеры кривой     // #include <qwt_symbol.h>     QwtSymbol *symbol = new QwtSymbol( QwtSymbol::Ellipse,         QBrush( Qt::yellow ), QPen( Qt::red, 2 ), QSize( 8, 8 ) );     curve->setSymbol( symbol );      // Добавить точки на ранее созданную кривую     // Значения точек записываются в массив, затем считываются     // из этого массива     for (int i = 0; i < 5; i++) {         points << QPointF( 1.0 * i, 1.0 * i); // произвольное заполнение     }      curve->setSamples( points ); // ассоциировать набор точек с кривой      curve->attach( ui->Qwt_Widget ); // отобразить кривую на графике }  void MainWindow::enableMagnifier() {     // #include <qwt_plot_magnifier.h>     QwtPlotMagnifier *magnifier =             new QwtPlotMagnifier(ui->Qwt_Widget->canvas());     // клавиша, активирующая приближение/удаление     magnifier->setMouseButton(Qt::MidButton); }  void MainWindow::enableMovingOnPlot() {     // #include <qwt_plot_panner.h>     QwtPlotPanner *d_panner = new QwtPlotPanner( ui->Qwt_Widget->canvas() );     // клавиша, активирующая перемещение     d_panner->setMouseButton( Qt::RightButton ); }  void MainWindow::enablePicker() {     // #include <qwt_plot_picker.h>     // настройка функций     QwtPlotPicker *d_picker =             new QwtPlotPicker(                 QwtPlot::xBottom, QwtPlot::yLeft, // ассоциация с осями     QwtPlotPicker::CrossRubberBand, // стиль перпендикулярных линий     QwtPicker::AlwaysOn, // всегда включен     ui->Qwt_Widget->canvas() ); // ассоциация с полем      // Цвет перпендикулярных линий     d_picker->setRubberBandPen( QColor( Qt::red ) );      // цвет координат положения указателя     d_picker->setTrackerPen( QColor( Qt::black ) );      // непосредственное включение вышеописанных функций     d_picker->setStateMachine( new QwtPickerDragPointMachine() ); } 

Выполненные действия позволяют нам отображать график непосредственно в форме, причем размеры его полотна соответствуют размерам «Qwt_Widget». Попробуйте после компиляции и запуска программы изменить размеры формы. Размеры «Qwt_Widget», естественно, не изменяются. Чтобы это происходило, необходимо воспользоваться «Layout». Эту стандартную (исхоженную и изъезженную) процедуру я решил не описывать в статье.

Отобразим координат клика в строке состояния Designer Form

1. Добавим код в прототип класса MainWindow в файле mainwindow.h

private Q_SLOTS: void click_on_canvas( const QPoint &pos ); 

реализуем слот (функцию) в mainwindow.cpp:

void MainWindow::click_on_canvas( const QPoint &pos ) {     // считываем значения координат клика     double x = ui->Qwt_Widget->invTransform(QwtPlot::xBottom, pos.x());     double y = ui->Qwt_Widget->invTransform(QwtPlot::yLeft, pos.y());      statusBar()->showMessage("x= " + QString::number(x) +                              "; y = " + QString::number(y)); } 

В функцию enablePicker() добавляем следующую строчку:

    connect( d_picker, SIGNAL( appended( const QPoint & ) ),             SLOT( click_on_canvas( const QPoint & ) ) ); 

Как вариант, можно было бы объявить d_picker приватной переменной класса MainWindow и делать вышеуказанный коннект «сигнал-слот» в конструкторе, либо в специальном методе.

Переместим кривую вдоль оси х

Здесь, так как визуализатор добавлен с помощью «Widget», все просто и знакомо:
1. Добавим элемент управления «Double Spin box» на форму и переименуем его на «changeXSpinBox».
2. Добавим элемент управления «PushButton» на форму и переименуем его на «moveByXButton». Изменим текст на кнопке на «Change x».
3. Для «moveByXButton» выполним команду «Go to slot»->clicked.
4. Функция должна выглядеть следующим образом:

void MainWindow::on_moveByXButton_clicked() {     double x = 0.0;     // Выполняется преобразование ',' на '.' для того, чтобы     // текст spinBox мог бы быть преобразован в double     QString spinBoxText = ui->changeXSpinBox->text().replace(                 QLocale().decimalPoint(), QLatin1Char('.'));      double xChangeValue = spinBoxText.toDouble();      for (int i = 0; i <points.size(); i++) {         x = points[i].x();         points[i].setX(x + xChangeValue);     }      curve->setSamples(points);     ui->Qwt_Widget->replot(); }  

Выводы: мы успешно воспользовались дизайнерскими средствами Qt Creator для создания визуализатора и его демонстрационных элементов управления. С помощью spinBox и кнопки мы можем изменять координату x точек отображаемой кривой.
В части №4 цикла статей мы реализуем дополнительные способы увеличения/уменьшения графика, выборку точек с помощью мышки, средства редактирования отображения графика и кривых, а также экспорт графика.

P.S. Выражаю огромную признательность Riateche за ценные замечания по статьям №1 и №2, которые были учтены при написании этой статьи.

Ссылки:

Исходники:
github.com/VladimirSap/Qwt_Tutorial

Официальный ресурс:
qwt.sourceforge.net

Сборник решений разнообразных пробем c Qwt:
www.qtcentre.org/archive/index.php/f-23.html

Вариант библиотеки, альтернативный Qwt (спасибо, GooRoo)
www.qcustomplot.com/

Ссылки на предыдущие статьи цикла:
Часть 1: habrahabr.ru/post/211204/
Часть 2: habrahabr.ru/post/211867/

Как вы предпочитаете добавлять элементы управления (виджеты)?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Никто ещё не голосовал. Воздержавшихся нет.

ссылка на оригинал статьи http://habrahabr.ru/post/212137/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *