Как исправить ошибку "index <m_series->count()" в xychart.cpp?
Я начал использовать QtCharts
в моем приложении. Диаграмма, которую я рассматриваю, представляет собой линейную диаграмму с использованием объектов. QChart
а также QLineSeries
, Поскольку все точки добавляются динамически, я использую систему сигнал / слот для обновления графика:
QLineSeries* serie = new QLineSeries(this);
connect(serie, SIGNAL(pointAdded(int)), this, SLOT(onPointAdded(int)));
void MyChart::onPointAdded(int index) {
// Delete the first items if the number of points has reached a threshold
while (serie->points().length() >= threshold)
serie->remove(0);
}
Функция onPointAdded
вызывается при добавлении точки в serie
(а QLineSeries
объект). Фрагмент кода, который я дал, удаляет первые точки в serie
например, количество точек на графике всегда фиксировано (кроме как в начале).
Когда я запускаю этот код в Release
, нет проблем. Тем не менее, когда я запускаю его на Debug
и количество баллов достигает порога, я получаю следующее сообщение об ошибке:
Это диалоговое окно не останавливает программу, но каждый раз, когда точка добавляется (и достигает порогового значения), появляется новое диалоговое окно поверх предыдущего.
Ниже приведен минимальный код для воспроизведения ошибки:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QChart>
#include <QLineSeries>
#include <QMainWindow>
#include <QValueAxis>
#include <QtCharts/QChart>
#include <QtCharts/QLineSeries>
QT_CHARTS_USE_NAMESPACE
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QChart* chart = nullptr;
QLineSeries* serie = nullptr;
int threshold = 5;
private slots:
void onAddPointButtonClicked();
void onPointAdded(int index);
};
#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);
chart = new QChart;
serie = new QLineSeries(this);
connect(ui->bt_addPoint, SIGNAL(clicked()), this, SLOT(onAddPointButtonClicked()));
connect(serie, SIGNAL(pointAdded(int)), this, SLOT(onPointAdded(int)));
chart->legend()->hide();
chart->addSeries(serie);
ui->graphicsView->setChart(chart);
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::onAddPointButtonClicked() {
serie->append(0, 1);
}
void MainWindow::onPointAdded(int index) {
while (serie->points().length() >= threshold)
serie->remove(0);
}
Я использовал UI Form для создания графического интерфейса. Этот интерфейс содержит QChartView
и QPushButton
(динамически добавлять точки).
Моя версия Qt - 5.11.2, и ошибка была создана с использованием MSVC 2017 64-bit. Плагин QtCharts необходим для использования QChart
, QChartView
а также QLineSeries
,
Я хотел бы знать, возможно ли исправить эту проблему или отключить сообщения диалога отладки Qt.
1 ответ
причина
Это не ошибка, но ожидаемый результат порядка, в котором слоты MainWindow::onPointAdded
(в вашем коде) и XYChart::handlePointAdded
выполнены. Вот вся история:
Из сообщения об ошибке становится ясно, что в файле xychart.cpp
по строке 142 проверка index
против счета m_series
выходит из строя. То, что делает чек недействительным, это ваша serie->remove(0);
, Причина в том, что ваш слот выполняется перед слотом, где производится проверка, потому что ваш connect
утверждение приходит первым. Вопрос: сначала к чему? Ну, это сложная часть, и я должен признать, что это действительно не сразу очевидно. Однако, покопавшись в исходном коде, можно добраться до сути проблемы. Путь следующий:
chart = new QChart;
в вашем коде создает экземплярQChart
который в свою очередь создает экземпляр PIMPLQChartPrivate
QChartPrivate
подключается в своем конструктореChartDataSet::seriesAdded
вChartPresenter::handleSeriesAdded
:QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_presenter, SLOT(handleSeriesAdded(QAbstractSeries*)));
ВАЖНО Теперь вы подключаетесь
QLineSeries::pointAdded
вMainWindow::onPointAdded
chart->addSeries(serie);
в вашем коде вызываетChartPresenter::handleSeriesAdded
слот для выполнения, гдеQLineSeriesPrivate::initializeGraphics
называется:series->d_ptr->initializeGraphics(rootItem());
В
QLineSeriesPrivate::initializeGraphics
LineChartItem
создается экземпляр:LineChartItem *line = new LineChartItem(q,parent);
LineChartItem
вызывает конструктор своего базового классаXYChart
в списке инициализатора своего собственного конструктораВАЖНО Только сейчас
connect
Выписка выполнена, что вызывает у вас неприятностиXYChart::handlePointAdded
слот, который вызывается при добавлении точки в ряд:QObject::connect(series, SIGNAL(pointAdded(int)), this, SLOT(handlePointAdded(int)));
Сосредоточив внимание только на шагах, отмеченных как важные, становится очевидным, в каком порядке connect
заявления приходят. Это также порядок, в котором вызываются соответствующие слоты.
Решение
Имея это в виду, я бы посоветовал вам сначала добавить серию в таблицу, а затем подключить pointAdded
сигнал, т.е.
переехать
connect(serie, SIGNAL(pointAdded(int)), this, SLOT(onPointAdded(int)));
после
chart->addSeries(serie);