2014-09-25 422 views
0

我目前通过串行通信接收的信息,请参阅下面的示例数据的未来:QCustomPlot - 各个选项卡中情节

"A Ch1:45.23 Ch2:23.58 Ch3:12.45 Ch4:1.56" 
"B Ch1:12.63 Ch2:15.45 Ch3:6.23 Ch4:45.32" 
"C Ch1:22.20 Ch2:3.85 Ch3:2.45 Ch4:51.58" 
"D Ch1:21.25 Ch2:2.58 Ch3:12.13 Ch4:61.52" 
"A Ch1:4.27 Ch2:25.52 Ch3:22.15 Ch4:31.56" etc. 

现在我所要做的是把所有的输入数据,并绘制它。为此,我创建了一个包含多个选项卡的Qt应用程序。

Tab 1 - All Sections 
Tab 2 - Section A 
Tab 3 - Section B 
Tab 4 - Section C 
Tab 5 - Section D 

我向每个选项卡添加了一个小部件,并将其推广到QCustomPlot。

我设置每个QCustomPlot如下:

// Would be nice to improve this 
setupGraph(ui->sectionA); // Setup Section A QCustomPlot 
setupGraph(ui->sectionB); // Setup Section B QCustomPlot 
setupGraph(ui->sectionC); // Setup Section C QCustomPlot 
setupGraph(ui->sectionD); // Setup Section D QCustomPlot 

void MainWindow::setupGraph(QCustomPlot *graphPlot) 
{ 
    QStringList legend; 

    legend << "Load Cell 1" << "Load Cell 2" << "Load Cell 3" << "Load Cell 4" << "Total Weight"; 

    graphPlot->legend->setVisible(true); 
    graphPlot->legend->setFont(QFont("Helvetica",9)); 

    for (int i = 0; i < legend.size(); i++) 
    { 
     graphPlot->addGraph(); 
     graphPlot->graph(i)->setName(legend[i]); 
     graphPlot->graph(i)->setLineStyle(QCPGraph::lsLine); 
    } 

    graphPlot->graph(0)->setPen(QPen(Qt::blue)); 
    graphPlot->graph(1)->setPen(QPen(Qt::red)); 
    graphPlot->graph(2)->setPen(QPen(Qt::green)); 
    graphPlot->graph(3)->setPen(QPen(Qt::darkCyan)); 
    graphPlot->axisRect()->setupFullAxesBox(); 
    graphPlot->xAxis->setRange(-10,0); 
    graphPlot->yAxis->setRange(0,5); 
    connect(graphPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), graphPlot->xAxis2, SLOT(setRange(QCPRange))); 
    connect(graphPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), graphPlot->yAxis2, SLOT(setRange(QCPRange))); 
} 

一旦做到这一点,我打开串口并连接到ReadyRead信号。每次有新数据可用时,我都会检查新数据来自哪里,我想绘制它。

void MainWindow::readData() 
{ 
    QByteArray serialData; 

    if (serial->canReadLine()) 
     serialData = serial->readLine(); 

    if (serialData.startsWith('A')) 
     realtimePlot(ui->sectionA) // Plot the data for Section A 
    if (serialData.startsWith('B')) 
     realtimePlot(ui->sectionB) // Plot the data for Section B 
    if (serialData.startsWith('C')) 
     realtimePlot(ui->sectionC) // Plot the data for Section C 
    if (serialData.startsWith('D')) 
     realtimePlot(ui->sectionD) // Plot the data for Section D 
} 

我省略了从输入数据中提取实际值的代码。

void MainWindow::realtimePlot(QCustomPlot *graphPlot) 
{ 
    range_y_min = 0; 
    range_y_max = 100; 
    // Add data to the lines 
    graphPlot->graph(0)->addData(key_x, ch1); 
    graphPlot->graph(1)->addData(key_x, ch2); 
    graphPlot->graph(2)->addData(key_x, ch3); 
    graphPlot->graph(3)->addData(key_x, ch4); 
    // Remove data outside the visible range 
    graphPlot->graph(0)->removeDataBefore(key_x-10); 
    graphPlot->graph(1)->removeDataBefore(key_x-10); 
    graphPlot->graph(2)->removeDataBefore(key_x-10); 
    graphPlot->graph(3)->removeDataBefore(key_x-10); 
    // Make the x-axis range scroll with the data (at a constant range size of 10): 
    graphPlot->xAxis->setRange(key_x+1/frequency,10,Qt::AlignRight); 
    // Set the range of the y-axis 
    graphPlot->yAxis->setRange(range_y_min,range_y_max+5); 
    // Replot the graph 
    graphPlot->replot(); 
    key_x += 1/frequency; // defines horizontal gap between two data points on graph 
} 

现在我希望removeDataBefore(key_x-10)删除之前这一点,所有的数据,因为我发现我的记忆相当迅速填补。 key_x和频率在其他地方定义。

我目前拥有的代码(类似于上面的代码)确实有效,但过了一段时间,一切开始放缓,一切都被推迟。所以我不太确定什么是错的或导致这种情况发生。我还想知道如何使用标签1中的部分A,部分B,部分C和部分D的图,因为我不想在第一个标签上创建另外4个小部件来绘制数据。

我希望我给你足够的背景资料。

非常感谢您的帮助。

回答

0

关于你的第二个问题,它很简单。 只需将图形添加到一个控件(也许更改颜色等)

只需将addGraph()调用到一个图形对象即可。

这也可能会提高您的速度,因为您不会为每个图形对象调用replot()。

+0

我知道我可以将多个图形添加到一个窗口小部件,但是我不太确定如何在一个窗口小部件上获得散点图和正常图形,然后如何让它们都实时显示。无论如何,为了加快速度,我使用了一个计时器并每隔一段时间调用一次。似乎加快了一点。 – skandebaba 2014-10-12 21:31:28

+0

你想在同一个地块或只是相同的小部件内散射和正常吗?我有一个类似的问题,我用一个单独的线程来读取数据(在你的情况下串行COM端口),该线程然后发出一个信号到必要的窗口来更新。这样我只在新数据进来时更新,而不是基于任意定时器。 – 2014-10-14 14:23:47

+0

我想在同一个窗口小部件中有散点图和正常情节(所以只有一个QWidget升级到QCustomPlot并且在这个小部件中都有绘图)。这将是一个很好的解决方案,我之前从未使用线程,所以我不知道如何去使用单独的线程来读取数据,而使用另一个线程来更新必要的窗口。你知道有什么好的链接来帮助我开始这个吗? – skandebaba 2014-10-16 02:23:52