В примерах использованы 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. Это сделано специально, так как хотелось сделать статьи независимыми друг от друга.
2. Открываем редактор формы и находим виджет «Widget». Размещаем его на форме.

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

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

Обратите особое внимание на следующее. Раньше мы создавали приватную переменную QwtPlot *d_plot, а затем использовали такую конструкцию, как, например:
d_plot->setTitle( "Qwt demonstration" );
Теперь для настроек свойств графика мы будем использовать следующую конструкцию:
ui->Qwt_Widget->setTitle( "Qwt demonstration" );
Причем, если в коде отсутствуют такие конструкции, то «Qwt_Widget» является пустым. После добавления строчки с настройкой этот виджет начинает отображать поле графика.
#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
#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». Эту стандартную (исхоженную и изъезженную) процедуру я решил не описывать в статье.
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 и делать вышеуказанный коннект «сигнал-слот» в конструкторе, либо в специальном методе.
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/
Добавить комментарий