Интерфейс масштабирования и перемещения графика QwtPlot в стиле
TChart из библиотеки компонентов Delphi
В статье "Пример использования виджета
QwtPlot из библиотеки Qwt" рассматривается интерфейс ScrollZoomer
масштабирования и перемещения графика из примера realtime,
поставляемого вместе с библиотекой Qwt. Он позволяет нажатием на
левую кнопку мыши выделить на канве какую-либо область графика и
увидеть ее в увеличенном масштабе. Кроме того, после перерисовки
графика на канве появляются полосы прокрутки, с помощью которых
можно перемещать просматриваемую область. Вернуться к исходному
масштабу графика можно, нажав правую кнопку мыши. Готовый проект
с подключенным интерфейсом ScrollZoomer
доступен по ссылке.
Полосы прокрутки позволяют двигать график только в горизонтальном
и вертикальном направлении, что не всегда удобно иногда хочется
перемещать его по диагонали. На мой взгляд, на много удобнее интерфейс
масштабирования и перемещения графика у компонента TChart
из библиотеки компонентов Delphi и C++Builder. Выделение области,
определяющей новые границы графика, производится так же левой кнопкой
мыши движением слева направо и сверху вниз. При отпускании левой
кнопкой мыши график изменяет свой масштаб. Если попытаться выделить
область в противоположном направлении, то при отпускании кнопки
мыши границы графика вернутся к исходному состоянию. Перемещение
графика (причем в любом направлении) производится при нажатой правой
кнопке мыши. Для сравнения интерфейсов Вы можете посмотреть проект
Delphi с аналогичным графиком.
Вашему вниманию предлагается класс QwtChartZoom,
который обеспечивает интерфейс масштабирования и перемещения графика
QwtPlot в стиле TChart
из библиотеки компонентов Delphi и C++Builder. Кроме того, имеется
два класса QWheelZoomSvc и QAxisZoomSvc,
которые придают интерфейсу масштабирования некоторую дополнительную
функциональность.
Первое дополнение класс QWheelZoomSvc
поддерживает изменение масштаба вращением колеса мыши при
нажатой клавише <Ctrl> или <Shift>.
Если нажата клавиша <Ctrl>, то масштабирование
производится и по вертикольной оси, и по горизонтальной. Если нажат
левый <Shift>, то изменяется масштаб
только по вертикальной шкале, если правый <Shift>,
только по горизонтальной.
Второе дополнение класс QAxisZoomSvc
позволяет изменять одну из границ шкалы, путем ее перетаскивания
мышью так, как показано на рисунке
Если потянуть за правую половину горизонтальной шкалы,
то будет меняться правая граница графика, если за левую, соответственно,
левая. Аналогично, если потянуть за верхнюю половину вертикальной
шкалы, то будет меняться верхняя граница графика, если за нижнюю,
соответственно, нижняя.
Рассмотрим порядок подключения интерфейса QwtChartZoom
к своему графику.
Пусть виджет QwtPlot с именем myPlot
размещен на форме главного окна приложения. Ниже приведены заголовочный
файл и файл реализации класса MainWindow.
файл "mainwindow.h"
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
Место для размещения дополнительных директив
#include
namespace Ui {
class MainWindow;
}
class MainWindow
: public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget
*parent = 0);
~MainWindow();
private:
Ui::MainWindow
*ui;
Место для размещения для
указатей на элементы графика, менеджер масштабирования и его дополнения
}
#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);
Место для размещения инструкций наполнения графика,
подключения менеджера масштабирования и его дополнений
}
MainWindow::~MainWindow()
{
Место для размещения инструкций удаления менеджера
масштабирования, его дополнений и элементов графика
delete ui;
}
Если форма разрабатывалась с помощью Qt Designer,
то класс MainWindow определен в пространстве
имен Ui, и доступ ко всем элементам формы
осуществляется через указатель ui: например,
ui->myPlot. Пустой график создается при
выполнении инструкции ui->setupUi(this)
в конструкторе главного окна приложения. Далее следует наполнение
графика: создаются кривые с данными, устанавливаются свойства шкал
и т.п. (пример оформления графика приведен в упомянутой выше статье).
После перестроения графика здесь же в конструкторе к нему подключается
менеджер масштабирования и перемещения экземпляр класса QwtChartZoom
вместе с дополнениями QWheelZoomSvc и QAxisZoomSvc.
Понятно, что в свой проект надо добавить файлы, реализующие эти
классы. В деструкторе перед удалением объектов из пространства имен
Ui командой delete ui
сначала удаляются менеджер масштабирования и его дополнения, а также
все элементы графика, созданные в конструкторе командой new.
Для того чтобы иметь доступ к этим элементам в деструкторе, указатели
на них должны являться членами класса MainWindow
и быть объявленными в заголовочном файле.
Таким образом, последовательность подключения интерфейса QwtChartZoom
следующая
1. Копируем в папку со своим проектом файлы
"qwtchartzoom.h", "qwtchartzoom.cpp",
"qwheelzoomsvc.h", "qwheelzoomsvc.cpp",
"qaxiszoomsvc.h" и "qaxiszoomsvc.cpp",
которые доступны по ссылке.
Если какое-то из дополений QWheelZoomSvc
или QAxisZoomSvc не планируется использовать
в проекте, то понятно, что файлы этого класса копировать не надо.
2. Добавляем скопированные файлы в свой проект
SOURCES += qwtchartzoom.cpp\
qwheelzoomsvc.cpp\
qaxiszoomsvc.cpp
HEADERS +=qwtchartzoom.h\
qwheelzoomsvc.h\
qaxiszoomsvc.h
Опять же, заголовочные файлы и файлы исходного кода
классов QWheelZoomSvc и QAxisZoomSvc
необходимо добавлять в проект только в том случае, если запланировано
их использовать.
3. В заголовочный файл "mainwindow.h"
включаем дополнительные директивы #include
#include "qwtchartzoom.h"
#include "qwheelzoomsvc.h"
(если надо)
#include "qaxiszoomsvc.h"
(если надо)
4. В секции private
объявляем указатели на менеджер масштабирования и перемещения графика
QwtChartZoom *zoom;
и его дополнения
QWheelZoomSvc *whlzmsvc;
(если надо)
QAxisZoomSvc *axzmsvc;
(если надо)
5. В конструкторе главного окна приложения (файл
"mainwindow.cpp") создаем экземпляр
класса QwtChartZoom, и, если необходимо,
переопределяем цвет каймы выделяемой области, задающей новый масштаб
графика
zoom = new
QwtChartZoom(ui->myPlot);
zoom->setRubberBandColor(Qt::white);
Здесь же, если запланировано, создаем экземпляр класса
QWheelZoomSvc, и прикрепляем его к менеджеру
масштабирования
whlzmsvc = new
QWheelZoomSvc();
whlzmsvc->attach(zoom);
Далее, если запланировано, создаем экземпляр класса
QAxisZoomSvc, и прикрепляем его к менеджеру
масштабирования
axzmsvc = new
QAxisZoomSvc();
axzmsvc->attach(zoom);
6. В деструктор вставляем команды удаления объектов
delete axzmsvc;
(если надо)
delete whlzmsvc;
(если надо)
delete zoom;
Готовый проект с подключенным интерфейсом доступен по
ссылке.
По умолчанию всякое изменение масштаба или границ графика прорисовывется
немедленно. Это создает определенную нагрузку на графическую систему.
Поэтому на "слабых" компьютерах менеджер масштабирования
во время выполнения некоторых операций, таких как перемещение графика
или изменения одной из границ шкалы, может "притормаживать".
В большей степени это проявляется при использовании библиотеки Qwt 6.x.x.
Для таких случаев предусмотрен "легкий" режим интерфейса.
Если он включен, то при перемещении графика, например, вместо него
перемещается индикатор, изображающий канву графика, а прорисовка
самого графика осуществляется только по завершении операции
отпускания правой кнопки мыши. Функции включения "легкого"
режима, назначения стиля и цвета индикатора приведены ниже. Аналогично
предусмотрен "легкий" режим для дополнения QAxisZoomSvc.
Прорисовка графика после изменения границы шкалы производится только
после отпускания левой кнопки мыши, а во время операции отображается
индикатор, показывающий размер видимой части шкалы в новом масштабе.
На графике могут присутствовать сразу две вертикальные шкалы (или
две горизонтальные). Масштаб на них может не совпадать, но переход
от одной шкалы к другой осуществляется с помощью линейного преобразования.
Координатная сетка привязана к одной из шкал. Могут отличаться и
шрифты, использующиеся на шкалах. Класс QwtChartZoom
умеет корректно работать с такими графиками.
Простой пример, пусть на графике изображены суточные колебания
температуры, на левой шкале значения температуры по шкале Цельсия,
а на правой по шкале Фаренгейта. Шкалы связаны между собой
соотношением
F = 1.8·t + 32,
где F температура по
шкале Фаренгейта, t по шкале Цельсия.
Координатная сетка привязана к левой шкале. Проект, иллюстрирующий
приведенный пример, можно взять здесь.
Для дополнительной демонстрации в интерфейсе масштабирования включен
"легкий" режим.
Перечислим имеющиеся функции управления интерфейсом и его дополнениями
void
QwtChartZoom::fixBoundaries()
Фиксирует текущие границы графика в качестве исходных. Отмена масштабирования
и перемещения будет возвращать график имеено к этим границам.
void
QwtChartZoom::setRubberBandColor(QColor)
Устанавливает цвет каймы выделяемой области, задающей новый размер
графика, (по умолчанию черный).
void
QwtChartZoom::setLightMode(bool)
Включает/выключает "легкий" режим перемещения графика
(по умолчанию выключен).
void
QwtChartZoom::indicateDragBand(QwtChartZoom::QDragIndiStyle)
Задает стиль индикатора перемещения графика в "легком"
режиме. Аргумент может принимать значения
QwtChartZoom::disNone
индикация отключена;
QwtChartZoom::disSimple
упрощенная индикация;
QwtChartZoom::disDetailed подробная
индикация.
(По умолчанию задан стиль QwtChartZoom::disSimple.)
void
QwtChartZoom::setDragBandColor(QColor)
Устанавливает цвет индикатора перемещения графика в "легком"
режиме (по умолчанию черный).
void
QWheelZoomSvc::attach(QwtChartZoom
*)
Подключает дополнение QWheelZoomSvc к интерфейсу
масштабирования.
void
QWheelZoomSvc::setWheelFactor(double)
Задает коэффициент масштабирования графика при вращении колеса мыши
(по умолчанию коэффициент равен 1.2).
void
QAxisZoomSvc::attach(QwtChartZoom
*)
Подключает дополнение QAxisZoomSvc к интерфейсу
масштабирования.
void
QAxisZoomSvc::setLightMode(bool)
Включает/выключает "легкий" режим изменения границы шкалы
(по умолчанию выключен).
void
QAxisZoomSvc::indicateDragBand(bool)
Включает/выключает индикацию изменения границы шкалы в "легком"
режиме (по умолчанию индикация включена).
void
QAxisZoomSvc::setAxisRubberBandColor(QColor)
Устанавливает цвет индикатора изменения границы шкалы в "легком"
режиме (по умолчанию черный).
В дополнение к представленному имеется класс QChartSynZoom,
который умеет управлять масштабом сразу нескольких графиков, у которых
синхронизирована горизонтальная шкала. О нем можно прочитать в статье
Синхронное масштабирование графиков.
Данная статья освещает ипользование класса QwtChartZoom
версии 1.5.2. Доступны также старые редакции статьи о версиях 1.1
и 1.0.
|