我想在将新点添加到添加到它的QChart后添加新​​的QLineSeries
目的是将其用于显示以高速率(高达40万pts/秒)采集的数据,并在点到达数据包时更新绘图。

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

主窗口:

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

最佳答案

首先,如果您将在GUI线程中以400000 pts/sec的速度接收和附加点,则您的应用程序将被完全卡住。因此,您需要将另一个线程专用于数据接收和处理,并使用(例如)与QueuedConnection连接的信号/插槽将处理后的图形数据发送到GUI线程。 “处理”是指至少某种程度的抽取(平均,下降,抽取,这是那些DSP专家所理解的),因为400000 pts/sec的速度似乎很快,所以您会浪费内存和GUI性能。但是,如果您不想抽取,则取决于您。在这种情况下,您可以考虑使用比QueuedConnection编码的信号/插槽更轻便的数据传输机制。

第二个问题是何时绘制?不久前,我以更低的速率实现了QCustomPlot的类似功能。我遇到的主要问题是在接收到每个点后尝试重新绘制时(特别是在绘制抗锯齿图时)存在巨大的(且变化不定的)滞后。在您的情况下,解决方案是将QChartView子类化(我想您已经做到了),覆盖其中的timerEvent并在需要启动/停止重新绘制时调用startTimer()/killTimer()。另外,您可以在拥有QChartView对象的对象中持有一个计时器,然后从那里进行重绘,但是与子类QChartView相比,它看起来像是抽象泄漏。总而言之,这种方法可让您获得几乎恒定的帧速率,并在不卡住应用程序界面的情况下使其尽可能平滑。

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

09-06 06:03