c++ - 如何修复 xychart.cpp 中的 "index < m_series->count()"错误?

标签 c++ qt qtcharts qdebug

我开始使用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);
}

函数 onPointAddedserie(一个 QLineSeries 对象)中添加一个点时被调用。我给出的代码片段删除了 serie 中的第一个点,例如图中的点数始终是固定的(开头除外)。

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

Qt Debug Error Message

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

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

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

我的Qt版本是5.11.2,这个bug是用MSVC 2017 64-bits产生的。使用 QChart 需要插件 QtCharts , QChartViewQLineSeries .

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

最佳答案

原因

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

从错误消息中可以清楚地看出,在文件 xychart.cpp 的第 142 行,检查 indexm_series 的计数> 失败。使检查无效的是您的 serie->remove(0);。原因是您的插槽在进行检查的插槽之前执行,因为您的connect 语句首先出现。问题是:首先要什么?好吧,这是棘手的部分,我不得不承认它确实不是很明显。然而,通过深入挖掘源代码,可以找到问题的根源。路径如下:

  • chart = new QChart; 在您的代码中实例化一个 QChart,它又是 instantiates一个 PIMPL QChartPrivate

  • QChartPrivate connects in it's constructor ChartDataSet::seriesAddedChartPresenter::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 calls其基类 XYChart 的构造函数在其自身构造函数的初始化列表中

  • 重要 现在只有 connect 语句 executed ,这会给你带来麻烦 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);

关于c++ - 如何修复 xychart.cpp 中的 "index < m_series->count()"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53025680/

相关文章:

c++ - 将常规值轴更改为对数轴时出现问题

c++ - Linux下如何检测另一个进程并与其通信?

c++ - 设置套接字选项以减少 tcp 段之间的时间延迟

python - PyQt5 : widget not displayed after being added to layout

c++ - y 轴的 QtCharts 自动范围

c++ - QChartView QLineSeries 通过鼠标点击选择

c++ - 如何使用在包含使用符号的文件的文件中声明的符号(函数、字段、类等)。 C++

c++ - Boost::signal 内存访问错误

c++ - QTreeView 禁止显示根节点

c++ - 将字符串转换为 char* 问题