我想在将新点添加到添加到它的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
方法,该方法可以满足您的需求。