如何重新绘制QChart

时间:2016-08-06 12:12:21

标签: c++ qt qtchart

我想知道在添加新QChart新点后,如何重新标记QLineSeries 目标是使用它来显示以高速率(高达400 000点/秒)采集的数据,并在点到达数据包时更新绘图。

这是我一直在研究的测试程序:

主窗口:

class MainWindow : public QMainWindow{
    Q_OBJECT

    QLineSeries *series;
    QChart *chart;
    QChartView *chartView;

    int cnt=0;


public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pB_Start_clicked();

private:
    Ui::MainWindow *ui;
};

MainWindow构造函数:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){
    ui->setupUi(this);

    series = new QLineSeries();

    chart = new QChart();
    chart->setBackgroundRoundness(0);

    chart->addSeries(series);

 // A bunch of formatting
    chart->setBackgroundVisible(false);
    chart->setMargins(QMargins(0,0,0,0));
    chart->layout()->setContentsMargins(0,0,0,0);
    chart->legend()->hide();
    chart->setPlotAreaBackgroundBrush(QBrush(Qt::black));
    chart->setPlotAreaBackgroundVisible(true);
    chartView = new QChartView(chart);
    ui->gridLayout->addWidget(chartView);

}

用于向系列添加点数的pushButton clicked事件:

void MainWindow::on_pB_Start_clicked(){
    series->append(cnt,qSin(cnt/10));
    cnt++;
    // Update plot here << ======== HOW?
}

OpenGLSeries示例以某种方式完成它。我不明白怎么做。但是这种情况有点不同,因为它用新的替换系列中的所有点,而不是附加它们。

2 个答案:

答案 0 :(得分:3)

显然QCharts不需要repaint()。在系列中添加新点似乎就足够了。我没有看到数据,因为我没有为char设置轴,也因为没有正确计算值。

更正后的代码:

部首:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){
    ui->setupUi(this);

    series = new QLineSeries();

    chart = new QChart();    
    chart->addSeries(series);

    chart->createDefaultAxes(); // Preparing the axis
    chart->axisX()->setRange(0,10); 
    chart->axisY()->setRange(0,10); 

    // Same formatting
    chart->setBackgroundVisible(false);
    chart->setMargins(QMargins(0,0,0,0));
    chart->layout()->setContentsMargins(0,0,0,0);
    chart->legend()->hide();
    chart->setPlotAreaBackgroundBrush(QBrush(Qt::black));
    chart->setPlotAreaBackgroundVisible(true);
    chartView = new QChartView(chart);
    ui->gridLayout->addWidget(chartView);
}

pushButton代码,在计算之前将cnt转换为双倍。

void MainWindow::on_pB_Start_clicked(){
    double val = 3*(qSin((double)cnt*2)+2);
    series->append(cnt,val); // Enough to trigger repaint!
    cnt++;
}

答案 1 :(得分:2)

首先,如果您将在GUI线程中以400000点/秒的速度接收和追加积分,您的应用程序将完全冻结。因此,您需要将另一个线程专用于数据接收和处理,并使用(例如)与QueuedConnection连接的信号/插槽将处理后的图形数据发送到GUI线程。通过“处理”我的意思是至少某种抽取(平均,丢弃,抽取,就像那些DSP人员所理解的那样),因为400000 pts / sec似乎很快,你将浪费你的内存和GUI性能。但如果你不想摧毁,那取决于你。在这种情况下,您可以考虑比QueuedConnection ed信号/插槽更轻量级的数据传输机制。

第二个问题是何时策划?不久前,我以更低的费率与QCustomPlot实现了类似的功能。我遇到的主要问题是当我在接收到每个点后尝试重新绘制时出现了巨大的(并且变化的)延迟,特别是在绘制抗锯齿图时。在您的情况下,解决方案是子类QChartView(我想您已经完成了),覆盖timerEvent并在需要启动时调用startTimer() / killTimer() /停止重新绘制。或者,您可以在拥有QChartView对象的对象中持有计时器并从那里发出重新绘制,但与子类QChartView相比,它看起来像抽象泄漏。总而言之,这种方法允许您实现几乎恒定的帧速率,并使其平滑,无需冻结应用程序的界面。

最后,如何重新绘制? QChartView似乎从repaint()继承了QWidget方法,可以满足您的需求。