【问题标题】:How to repaint a QChart如何重新绘制 QChart
【发布时间】:2016-12-12 18:02:01
【问题描述】:

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

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

主窗口:

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 示例以某种方式做到了这一点。我不明白怎么做。但这种情况有点不同,因为它将系列中的所有点替换为新点,而不是附加它们。

【问题讨论】:

  • on_pB_Start_clicked 被调用时会发生什么?它是只为系列添加一个点还是开始以高速率添加点?
  • 在这个例子中,它所做的只是添加另一个点。这是我为了解QChart 的功能而构建的测试程序。但目标是以高速率进行绘图。

标签: c++ qt qtcharts


【解决方案1】:

显然 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 转换为 double。

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

【讨论】:

  • 如果您使用的是AreaSeries,那么您可以使用setUpperSeries(new_useries_here)setLowerSeries(new_lseries_here) 进行更新。您的 areaSeries 必须存储为全局变量。
  • easy_chart.cpp:72:12: warning: 'axisX' is deprecated qchart.h:109:5: note: 'axisX' has been explicitly marked deprecated here qcompilerdetection.h:227:45: note: expanded from macro 'Q_DECL_DEPRECATED'
【解决方案2】:

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

第二个问题是什么时候绘制?不久前,我用QCustomPlot 以低得多的速率实现了类似的功能。我面临的主要问题是,当我在收到每个点后尝试重新绘制时,尤其是在绘制抗锯齿图时,会出现巨大(且变化不定)的滞后。在您的情况下,解决方案是子类化QChartView(我想您已经完成了),覆盖其中的timerEvent,并在您需要开始/停止重新绘制时调用startTimer()/killTimer()。或者,您可以在拥有QChartView 对象的对象中保存一个计时器并从那里重新绘制,但与子类化QChartView 相比,它看起来像是抽象泄漏。总而言之,这种方法可以让您实现几乎恒定的帧速率,并使其尽可能流畅,而不会冻结应用程序的界面。

最后,如何重新绘制? QChartView 似乎继承自 QWidgetrepaint() 方法可以满足您的需要。

【讨论】:

  • 就是这样。 repaint() 似乎做到了。我只需要预定义比例或类似的东西。是的,400 000 pts/s 很多,我从来没有在我的主应用程序中绘制过这么多。到目前为止,我一直在使用 qwt 绘制图形,使用 QwtPlotDirectPainter 一次只绘制几个点,与 QCoreApplication::processEvents() 一起使用以保持 GUI 运行并运行良好。但是我看到 QCharts 使用 OpenGL,所以我打算改变。
  • @A.Vieira Qwt 通常声称比 QCustomPlot 快得多。可能它也比 QCharts 快,我不知道。如果要谈论规模,请在每次重新绘制之前考虑基于数据的重新缩放。在绘图的最初几秒钟内,它可能会让用户感到困惑,但它解决了错误的预定义比例可能出现的问题。
  • 从我在 OpenGLSeries 中看到的情况来看,每次绘制新数组时,使用 OpenGL 比使用 Qwt 更快。我不知道如何在 Qwt 中使用 OpenGL,它似乎仍在开发中但可能(不要引用我的话)。我在 Qwt 上取得了成功,但 QCharts 可能更稳定,可以在许多电脑上开发并将我的工作传递给同事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
  • 2023-02-19
  • 2016-07-19
  • 1970-01-01
  • 2014-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多