Использование гистограмм Qt Charts совместно с моделями данных

MVC (модель-представление-контроллер) — это паттерн проектирования, созданный на основе Smalltalk, который часто используется при создании пользовательских интерфейсов. В «Паттернах проектирования» Э. Гамма и др. написано:
MVC состоит из трех типов объектов. Модель – это объект приложения, Представление – это его экранное представление, а Контроллер определяет способ реакции пользовательского интерфейса на ввод пользователя. До MVC проекты пользовательского интерфейса имели тенденцию объединять эти объекты вместе. MVC разделяет их для повышения гибкости и повторного использования.
Qt так же содержит набор классов, которые для управления связями между данными и способами их представления пользователю используют архитектуру модель/представление. Разделение функций, введенное этой архитектурой, дает разработчикам большую гибкость для настройки представления элементов и предоставляет стандартный интерфейс модели, позволяющий использовать широкий диапазон источников данных с существующими представлениями элементов.
В данном примере мы будем использовать одну модель (источник данных) для одновременного преставления данных из нее двумя способами: в таблице и на диаграмме.
Использование моделей данных с гистограммами
Для простоты всё создание диаграммы выполним в конструкторе объекта класса, который наследуется от QMainWindow .
Начнем с создания экземпляра класса CustomTableModel . Класс CustomTableModel является производным от QAbstractTableModel и был создан только для этого примера. Конструктор этого класса заполняет внутреннее хранилище данных модели данными, необходимыми для нашего примера работы с диаграммами.
m_model = new CustomTableModel;
Теперь у нас есть модель с данными, которые мы хотели бы отображать как на гистограмме, так и в QTableView . Объект QTableView уже создан в дизайнере, и теперь говорим ему использовать только что созданную модель в качестве источника данных. Для хорошего представления данных режим изменения размера заголовков tableView изменен на растягивающийся. В дизайнере также задана минимальная ширина виджета.
ui->tableView->setModel(m_model); ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_model->setParent(ui->tableView);
Теперь нам нужен экземпляр QChart для отображения на гистограмме тех же данных. Также включаем у него анимацию. Так легче увидеть, как изменение данных модели влияет на диаграмму.
QChart *chart = new QChart; chart->setAnimationOptions(QChart::AllAnimations);
Первая строка приведенного ниже кода создает новый объект последовательности полос. Переменные firstRow и rowCount используются для определения настраиваемого сопоставления модели. Настраиваемое сопоставление позволяет взять из модели только часть данных. В этом случае данные из пяти строк, начиная со строки с индексом 3. Следующие три строки создают преобразователь данных, экземпляр класса QVBarModelMapper , и указывают, что данные для наборов полос должны быть взяты из столбцов модели с индексами от 1 до 4 (включительно). Чтобы создать связь между последовательностью полос и моделью, мы передаем оба этих объекта преобразователю данных, т.е. объекту mapper класса QVBarModelMapper .
Наконец, добавляем к диаграмме последовательность полос series .
QBarSeries *series = new QBarSeries; int firstRow = 3; int rowCount = 5; QVBarModelMapper *mapper = new QVBarModelMapper(this); mapper->setFirstBarSetColumn(1); mapper->setLastBarSetColumn(4); mapper->setFirstRow(firstRow); mapper->setRowCount(rowCount); mapper->setSeries(series); mapper->setModel(m_model); chart->addSeries(series);
Чтобы показать в QTableView , какие данные соответствуют какому набору полос, в этом примере используется раскраска таблицы. Когда последовательность полос добавляется к диаграмме, ей назначается цвет в зависимости от выбранной в данный момент темы. Код ниже извлекает этот цвет из последовательности полос и использует его для создания фона ячеек QTableView . Раскрашивание другого представления не является частью функционала QChart .
// для хранения hex-кода цвета из последовательности полос QString seriesColorHex = "#000000"; // получаем цвет последовательности и используем его индикации области таблицы, отображаемой на диаграмме QList barsets = series->barSets(); for (int i = 0; i < barsets.count(); i++) < seriesColorHex = "#" + QString::number(barsets.at(i)->brush().color().rgb(), 16).right(6).toUpper(); m_model->addMapping(seriesColorHex, QRect(1 + i, firstRow, 1, barsets.at(i)->count())); >
Также неплохо было бы, чтобы на оси диаграммы были подписаны категории, которые описывали бы суть данных. В следующем фрагменте показано, как это сделать. Здесь для примера всё сильно упрощено, в реальном проекте эти категории так же брались бы из модели.
QStringList categories; categories append(categories); chart->addAxis(axisX, Qt::AlignBottom); series->attachAxis(axisX); QValueAxis *axisY = new QValueAxis(); chart->addAxis(axisY, Qt::AlignLeft); series->attachAxis(axisY);
Чтобы избежать настройки QGraphicsScene , мы используем класс QChartView , который делает это за нас. Указатель на объект QChart используется как параметр конструктора QChartView . Чтобы визуализация выглядела лучше, включаем антиалиасинг и устанавливаем минимальный размер виджета chartView .
QChartView *chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); chartView->setMinimumSize(640, 480);
И, наконец, помещаем виджет chartView в специально подготовленный в дизайнере виджет QGroupBox .
ui->chartGroupBox->layout()->addWidget(chartView);
В результате получаем приложение следующего вида. Изменение данных в таблице влияет на их представление на диаграмме.

Исходный код
Полный исходный код проекта доступен на GitHub.
Также ниже приведен код исходного файла mainwindow.cpp и, в частности, конструктора, котором создается гистограмма.
#include "mainwindow.h" #include "ui_mainwindow.h" #include using namespace QtCharts; //--------------------------------------------------------------------------------------- MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) < ui->setupUi(this); m_model = new CustomTableModel; ui->tableView->setModel(m_model); ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_model->setParent(ui->tableView); QChart *chart = new QChart; chart->setAnimationOptions(QChart::AllAnimations); QBarSeries *series = new QBarSeries; int firstRow = 3; int rowCount = 5; QVBarModelMapper *mapper = new QVBarModelMapper(this); mapper->setFirstBarSetColumn(1); mapper->setLastBarSetColumn(4); mapper->setFirstRow(firstRow); mapper->setRowCount(rowCount); mapper->setSeries(series); mapper->setModel(m_model); chart->addSeries(series); // for storing color hex from the series QString seriesColorHex = "#000000"; // get the color of the series and use it for showing the mapped area QList barsets = series->barSets(); for (int i = 0; i < barsets.count(); i++) < seriesColorHex = "#" + QString::number(barsets.at(i)->brush().color().rgb(), 16).right(6).toUpper(); m_model->addMapping(seriesColorHex, QRect(1 + i, firstRow, 1, barsets.at(i)->count())); > QStringList categories; categories append(categories); chart->addAxis(axisX, Qt::AlignBottom); series->attachAxis(axisX); QValueAxis *axisY = new QValueAxis(); chart->addAxis(axisY, Qt::AlignLeft); series->attachAxis(axisY); QChartView *chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); chartView->setMinimumSize(640, 480); ui->chartGroupBox->layout()->addWidget(chartView); > //--------------------------------------------------------------------------------------- MainWindow::~MainWindow() < delete ui; >//---------------------------------------------------------------------------------------
Теги
Сохранить или поделиться
На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.
В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.
Подключение QChartView как кастомного виджета в Qt Designer

Пытаюсь подключить QChartView как кастомный виджет, способом, описанным в документации. Делаю «Преобразовать в. «: Затем преобразовываю в него QGraphicView. При компиляции возникает ошибка в автоматически генерируемом файле формы:
C:\Users\Shmeisser\Documents\build-DBHandler-Desktop_Qt_5_7_1_MinGW_32bit-Debug\ui_dbanalyzewindow.h:34: ошибка: ‘QChartView’ does not name a type QChartView *graphicsView;
В .pro файл QT += charts подключено, проект пересобирал. В чем может быть проблема?
Отслеживать
задан 14 янв 2017 в 21:39
bronstein87 bronstein87
1,133 10 10 серебряных знаков 17 17 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
В «Преобразовать в. » нужно вписывать следующее:
Base class name: QWidget
Promoted class name: QtCharts::QChartView
Header file: QtCharts/QChartView
Global include: checked
Отслеживать
ответ дан 15 янв 2017 в 20:21
bronstein87 bronstein87
1,133 10 10 серебряных знаков 17 17 бронзовых знаков
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.3.8.5973
Qt/C++ — Урок 071. Динамическое создание графиков с QtCharts.

Разберём вариант создания графиков, когда необходимо добавлять большое количество графиков, которые создаются динамически. Подобный урок уже был в статье по динамическому созданию виджетов, только там добавлялись кнопки QPushButton . Здесь применяется тот же самый вариант работы. Выделяется память в куче, производится настройка виджета с графиком, и виджет добавляет в QScrollArea или QLayout, чтобы отобразить сам график в окне приложения. Приложение будет выглядеть следующим образом: В данном примере будет добавляться 5 графиков в горизонтальный Layout ( QHBoxLayout ). Также в примере будет добавлена всплывающая подсказка, которая содержит некоторую информацию. Например, номер графика и количество отсчётов.
Структура проекта
- Graphs.pro — профайл проекта;
- widget.h — заголовочный файл окна приложения;
- widget.cpp — файл исходных кодов окна приложения;
- widget.ui — форма окна приложения;
- main.cpp — файл с main функцией.
main.cpp создаётся по умолчанию и не изменяется в проекте. В файле widget.ui необходимо только создать размещение QHBoxLayout . Сделать это можно через графический дизайнер Qt.
В профайле проекта необходимо подключить модуль charts (он должен быть предварительно установлен, в виде предкомпилированных библиотек QtCharts доступен с версии Qt5.7).
QT += chartsВ заголовочном файле widget.h не производится никаких дополнительных изменений. Весь код будет содержаться в файле widget.cpp.
widget.h
#ifndef WIDGET_H #define WIDGET_H #include namespace Ui < class Widget; >class Widget : public QWidget < Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; >; #endif // WIDGET_Hwidget.cpp
#include "widget.h" #include "ui_widget.h" #include #include #include #include #include #include static int randomBetween(int low, int high, int seed) < qsrand(seed); // Установка базового числа для отсчёта рандома в qrand return (qrand() % ((high + 1) - low) + low); >using namespace QtCharts; Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) < ui->setupUi(this); // Инициализирующее число для установки базы рандома в qrand int seed = 0; for (int i = 0; i < 5; ++i) < // Создаём представление графика QChartView *chartView = new QChartView(this); // Добавляем его в горизонтальный Layout ui->horizontalLayout->addWidget(chartView); // Создаём случайную синусоиду seed = randomBetween(0, 100, seed); QLineSeries *series = new QLineSeries(); int k = 0; while (k // Создаём график и добавляем в него синусоиду QChart *chart = new QChart(); chart->addSeries(series); chart->legend()->hide(); chart->setTitle("Graphic"); // Добавим всплывающую подсказку для графика chart->setToolTip(QString("График №%1\n" "Количество отсчётов %2").arg(i + 1).arg(k)); // Настройка осей графика QValueAxis *axisX = new QValueAxis(); axisX->setTitleText("x, м"); axisX->setLabelFormat("%i"); axisX->setTickCount(1); chart->addAxis(axisX, Qt::AlignBottom); series->attachAxis(axisX); QValueAxis *axisY = new QValueAxis(); axisY->setTitleText("t, мс"); axisY->setLabelFormat("%g"); axisY->setTickCount(5); chart->addAxis(axisY, Qt::AlignLeft); series->attachAxis(axisY); // Устанавливаем график в представление chartView->setChart(chart); > > Widget::~Widget()
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
Рекомендуемые статьи по этой тематике
- Qt/C++ - Урок 031. QCustomPlot - строим график по времени
- Qt/C++ - Урок 032. Сохранение изображения в файл из QCustomPlot
- Qt/C++ - Урок 030. QCustomPlot - быстрый старт в работе с графиками
- Qt/C++ - Урок 014. Динамическое создание виджетов в Qt
По статье задано0 вопрос(ов)
Подписка на обсуждение 4
Подписка на раздел 343
Вам это нравится? Поделитесь в социальных сетях!
Qt/C++ - Урок 071. Динамическое создание графиков с QtCharts.

Разберём вариант создания графиков, когда необходимо добавлять большое количество графиков, которые создаются динамически. Подобный урок уже был в статье по динамическому созданию виджетов, только там добавлялись кнопки QPushButton . Здесь применяется тот же самый вариант работы. Выделяется память в куче, производится настройка виджета с графиком, и виджет добавляет в QScrollArea или QLayout, чтобы отобразить сам график в окне приложения. Приложение будет выглядеть следующим образом: В данном примере будет добавляться 5 графиков в горизонтальный Layout ( QHBoxLayout ). Также в примере будет добавлена всплывающая подсказка, которая содержит некоторую информацию. Например, номер графика и количество отсчётов.
Структура проекта
- Graphs.pro - профайл проекта;
- widget.h - заголовочный файл окна приложения;
- widget.cpp - файл исходных кодов окна приложения;
- widget.ui - форма окна приложения;
- main.cpp - файл с main функцией.
main.cpp создаётся по умолчанию и не изменяется в проекте. В файле widget.ui необходимо только создать размещение QHBoxLayout . Сделать это можно через графический дизайнер Qt.
В профайле проекта необходимо подключить модуль charts (он должен быть предварительно установлен, в виде предкомпилированных библиотек QtCharts доступен с версии Qt5.7).
QT += chartsВ заголовочном файле widget.h не производится никаких дополнительных изменений. Весь код будет содержаться в файле widget.cpp.
widget.h
#ifndef WIDGET_H #define WIDGET_H #include namespace Ui < class Widget; >class Widget : public QWidget < Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; >; #endif // WIDGET_Hwidget.cpp
#include "widget.h" #include "ui_widget.h" #include #include #include #include #include #include static int randomBetween(int low, int high, int seed) < qsrand(seed); // Установка базового числа для отсчёта рандома в qrand return (qrand() % ((high + 1) - low) + low); >using namespace QtCharts; Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) < ui->setupUi(this); // Инициализирующее число для установки базы рандома в qrand int seed = 0; for (int i = 0; i < 5; ++i) < // Создаём представление графика QChartView *chartView = new QChartView(this); // Добавляем его в горизонтальный Layout ui->horizontalLayout->addWidget(chartView); // Создаём случайную синусоиду seed = randomBetween(0, 100, seed); QLineSeries *series = new QLineSeries(); int k = 0; while (k // Создаём график и добавляем в него синусоиду QChart *chart = new QChart(); chart->addSeries(series); chart->legend()->hide(); chart->setTitle("Graphic"); // Добавим всплывающую подсказку для графика chart->setToolTip(QString("График №%1\n" "Количество отсчётов %2").arg(i + 1).arg(k)); // Настройка осей графика QValueAxis *axisX = new QValueAxis(); axisX->setTitleText("x, м"); axisX->setLabelFormat("%i"); axisX->setTickCount(1); chart->addAxis(axisX, Qt::AlignBottom); series->attachAxis(axisX); QValueAxis *axisY = new QValueAxis(); axisY->setTitleText("t, мс"); axisY->setLabelFormat("%g"); axisY->setTickCount(5); chart->addAxis(axisY, Qt::AlignLeft); series->attachAxis(axisY); // Устанавливаем график в представление chartView->setChart(chart); > > Widget::~Widget()
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
Рекомендуемые статьи по этой тематике
- Qt/C++ - Урок 031. QCustomPlot - строим график по времени
- Qt/C++ - Урок 032. Сохранение изображения в файл из QCustomPlot
- Qt/C++ - Урок 030. QCustomPlot - быстрый старт в работе с графиками
- Qt/C++ - Урок 014. Динамическое создание виджетов в Qt
По статье задано0 вопрос(ов)
Подписка на обсуждение 4
Подписка на раздел 343
Вам это нравится? Поделитесь в социальных сетях!
