0

我开始QtCharts在我的应用程序中使用。我正在考虑的图表是折线图,使用对象QChartQLineSeries。由于所有点都是动态添加的,我使用信号/槽系统来更新图表:

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中添加一个点时调用该函数。我给出的代码片段删除了图中的第一个点,例如图中的点数始终是固定的(开头除外)。serieQLineSeriesserie

当我在 中运行此代码时Release,没有问题。但是,当我运行它Debug并且点数达到阈值时,我收到以下错误消息:

Qt 调试错误信息

此对话框不会停止程序,但每次添加一个点(并达到阈值)时,都会在前一个对话框的顶部出现一个新对话框。

以下是重现错误的最少代码:

主窗口.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

主窗口.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 表单来生成图形界面。这个接口包含一个QChartView和一个QPushButton(动态添加点)。

我的 Qt 版本是5.11.2,并且该错误是使用MSVC 2017 64-bits产生的。需要插件QtCharts才能使用QChart,QChartViewQLineSeries.

我想知道是否可以解决此问题或禁用 Qt 调试对话框消息。

4

1 回答 1

2

原因

这不是错误,而是插槽MainWindow::onPointAdded(在您的代码XYChart::handlePointAdded中)执行顺序的预期结果。这是整个故事:

从错误消息中可以清楚地看出,在第xychart.cpp142 行的文件中,对失败index计数​​的检查。m_series使支票无效的东西是您的serie->remove(0);. 原因是您的插槽在进行检查的插槽之前执行,因为您的connect语句首先出现。问题是:首先到什么?好吧,这是棘手的部分,我不得不承认它确实不是立即显而易见的。但是,通过对源代码进行一些挖掘,可以找到问题的根源。路径如下:

  • chart = new QChart;在您的代码中实例化 a QChart,而后者又实例化PIMPLQChartPrivate

  • QChartPrivate 在它的构造函数中连接 ChartDataSet::seriesAddedChartPresenter::handleSeriesAdded

      QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_presenter, SLOT(handleSeriesAdded(QAbstractSeries*)));
    
  • 重要现在您连接QLineSeries::pointAddedMainWindow::onPointAdded

  • chart->addSeries(serie);在您的代码中导致ChartPresenter::handleSeriesAdded插槽被执行,其中QLineSeriesPrivate::initializeGraphics被称为:

      series->d_ptr->initializeGraphics(rootItem());
    
  • QLineSeriesPrivate::initializeGraphicsaLineChartItem中实例化:

      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);
于 2018-10-28T02:22:19.893 回答