Qt |使用QGraphicsView,QGraphics Scene |创建动态图表/绘图实时数据

问题描述:

我目前正在开发一个Qt中的小程序。要显示一个图,您可以使用qwt或qcustomplot或qpainterevent或QChart。但是我为QGraphicsView写的一个动态绘图解决方案而着迷。Qt |使用QGraphicsView,QGraphics Scene |创建动态图表/绘图实时数据

我的喜好 -width我的图表应该是恒定的 -realtime绘制 -the第一个样品应删除或自动覆盖,如果达到图表的末端,所以它是一个动态的,流畅的图表

我的下面的例子可以是动态的,流利的......但只是在我的if语句中的数字。我不明白为什么。

这个想法是删除第一个lineitem,所以我不断有99个项目。如果我删除一个项目,我想给下一个项目之前的项目的位置。所以 x = 99将是x = 98 ...... x = 1将是x = 0;

我的想法有错吗? 我也有过几个想法,但这可能是最好的。

在此先感谢 康拉德

MainWindow::MainWindow(QWidget *parent) : 
     QMainWindow(parent), 
     ui(new Ui::MainWindow) 
    { 
     ui->setupUi(this); 
     scene = new QGraphicsScene(this); 
     ui->graphicsView->setScene(scene); 
     vectorPoint = new QVector<QPoint>; 
     line = new QVector<QGraphicsLineItem*>; 

    yDatai = 0; 
    xDatai = 0; 
    Grenzenlaufvariable = 0; 

    timer = new QTimer(this); 
    timer->start(10); 
    connect (timer, SIGNAL(timeout()),this,SLOT(newData())); 
    connect(this,SIGNAL(newPaint()),this,SLOT(paint())); 
} 

MainWindow::~MainWindow() 
{ 
    delete ui; 
    delete scene; 
    delete vectorPoint; 
    delete line; 
    } 

    void MainWindow::newData() 
    { 

    if (yDatai == 100 || yDatai == -100)     
    { 
     Grenzenlaufvariable++; 
    } 
    if (Grenzenlaufvariable%2==0) 
    { 
     yDatai+=1; 
    } 
    else 
    { 
     yDatai-=1; 
    } 
    xDatai++; 

    point = {xDatai,yDatai};        
    vectorPoint->append(point); 

    if(vectorPoint->size()>1) 
    { 
     item = scene->addLine(QLineF(vectorPoint->at(ix-1),vectorPoint->at(ix))); 
     line->append(item); 
    } 
     ix++; 
    emit newPaint();          
} 

void MainWindow::paint() 
{ 
    if(line->size()==99) 
    { 

     scene->removeItem(line->at(0)); 
     line->removeAt(0); 
     qDebug()<<line->size(); 
     for (int ip= 0;ip <line->size();ip++) 
     { 
      oldx = line->at(ip)->x(); 
      line->at(ip)->setX(oldx-1); 
      qDebug()<<ip; 

     } 
    } 
} 
+0

你可以更好地解释我。 – eyllanesc

+0

你到底需要更好的解释?在我想要什么我编码? –

小心! 这些解决方案并不是最快的。使用QPainterPath而不是QLineF,它就像你拿笔,画一条线,把笔扔掉,这1000次。 更好地安全QPainterPath中的所有QPoint并拿起笔一次绘制。这增加了4分钟趋势和更多没有问题的实时绘图的性能。

到目前为止,这就是最好的答案,要注意的是,如果你使用的100Hz的采样率,我的表现只是50 samplesInView稳定。 您可以减少采样率并增加samplesInView以在图中具有更多值。

重要: xDatashortQVector<double>包括所有x值 yDatashortQVector<double>包括所有y值 两者都在programm类填充值,此类发射信号到连接其中启动槽drawGraph()

你也可以只使用QVector<QPoint>这使得它更容易处理,但它不是我想要的。

lineVectorQVector<QGraphicsLineItem>其inclues所有从视图

xScale线用于扩展的情节,yScale为好。

width是Coordinationsystem xAxisMark的宽度被以距离标记之间的pixeldistance marksVectorQVector<double>它包括X轴,这应该是动态

iCurrentVectorPoint的距离标记为runtimevariable,这有助于我添加行。

!!这段代码很适合实时绘图,但它没有最好的性能,所以如果有人有想法释放潜力,随时获得最佳答案:)!

如需进一步的问题,只需发表评论,我会尽力帮助您在设备上获得漂亮的手工绘图。

void Plot::drawGraph() 
{ 
    if(programm->xDatashort.size()>1) 
     { 
      if(lineVector->size()==programm->samplesInView) 
      { 
       for (int ip =0;ip<programm->samplesInView;ip++) 
       { 
        lineVector->at(ip)->setLine((ip)*xScale,(programm->yDatashort.at(ip))*yScale*(-1),(ip+1)*xScale,(programm->yDatashort.at(ip+1))*yScale*(-1)); 
       } 
       for (int iy=1 ; iy<(width/xAxisMarks)+1 ; iy++) 
       { 
        int oldx = marksVector->at(iy)->x(); 
        oldx-=1; 
        if(oldx%xAxisMarks==0 || oldx==0) 
        { 
        marksVector->at(iy)->setX(oldx+xAxisMarks); 
        } 
        else 
        { 
        marksVector->at(iy)->setX(oldx); 
        } 
       } 
      } 
      else 
      { 
       item = scene->addLine(QLineF(programm->xDatashort.at(iCurrentVectorPoint-1)*xScale, programm->yDatashort.at(iCurrentVectorPoint-1)*yScale*(-1), programm->xDatashort.at(iCurrentVectorPoint)*xScale, programm->yDatashort.at(iCurrentVectorPoint)*yScale*(-1))); 
       lineVector->append(item); 
      } 

     } 
     iCurrentVectorPoint++; 

} 

更新:

代码稳定超过50分钟,在视图800米的样品,用100赫兹采样率和20赫兹帧速率。使用线程模拟仿真。随意问我关于这个话题几乎一切,我通过它工作了近2个月:d

void MainWindow::drawChart() 
{ 
//To check the framerate I implemented a framecounter 
    framerunner++; 
    ui->Framerate->setText(QString::number(int(framerunner/double(DurationTimer->elapsed()/1000)))); 

//Using to stay focused on the scene, not neccesary if you define the x values from [startview-endview] 
    QRect a; 
    if(Samplevector.size()!=0) 
    { 
     a.setRect(Samplevector.at(Samplevector.size()-1).getX()-850,0,900,200); 
     qDebug()<<Samplevector.at(Samplevector.size()-1).getX(); 
    ui->LinegraphView->setSceneRect(a); 
    } 
//delete everything in the scene and redraw it again 
scene->clear(); 
if(Samplevector.size()>1) 
{ 
    for(int i=1;i<Samplevector.size();i++) 
    scene->addLine(QLineF(Samplevector.at(i-1).getX(),Samplevector.at(i-1).getY(),Samplevector.at(i).getX(),Samplevector.at(i).getY())); 
} 

} 
void MainWindow::start() 
{ 
    framerate->start(50); 
    DurationTimer->start(); 
    hegsimulator->moveToThread(thread); 
    thread->start(); 
    qDebug()<<"Request "<<this->QObject::thread()->currentThreadId(); 
} 
void MainWindow::stop() 
{ 
    framerate->stop(); 
    hegsimulator->stopDevice(); 
} 
void MainWindow::prepareGraph() 
{ 
    samplerunner++; 
    ui->Samplerate->setText(QString::number(int(samplerunner/double(DurationTimer->elapsed()/1000)))); 
    Samplevector.append(hegsimulator->getSample()); 
    if(Samplevector.size()>800) 
    { 
     //graphlinevector.first()->hide(); 
     //scene->removeItem(graphlinevector.first()); 
//  graphlinevector.removeFirst(); 
     Samplevector.removeFirst(); 
    } 
// if(Samplevector.size()>1) 
// { 
// item = scene->addLine(QLineF(Samplevector.at(Samplevector.size()-2).getX(),Samplevector.at(Samplevector.size()-2).getY(),Samplevector.at(Samplevector.size()-1).getX(),Samplevector.at(Samplevector.size()-1).getY())); 
// graphlinevector.append(item); 

// } 

}