【问题标题】:Qt | Creating a dynamic Chart / plot with QGraphicsView, QGraphics Scene | realtime dataQt |使用 QGraphicsView、QGraphics 场景创建动态图表/绘图 |实时数据
【发布时间】:2017-10-02 22:06:44
【问题描述】:

我目前正在用 Qt 开发一个小程序。要显示绘图,您可以使用 qwt 或 qcustomplot 或 qpainterevent 或 QChart。但我对使用 QGraphicsView 编写的动态绘图的解决方案感兴趣。

我的偏好 - 我的图表的宽度应该是恒定的 - 实时绘图 -如果到达图表末尾,则应删除或覆盖第一个样本,因此它是动态流畅的图表

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

想法是删除第一个lineitem,所以我一直有99个item。如果我删除一个项目,我想为下一个项目提供前一个项目的位置。 所以 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;

        }
    }
}

【问题讨论】:

  • 你可以更好地解释我。
  • 您究竟在哪里需要更好的解释?是我想要的还是我编码的?

标签: qt plot real-time qgraphicsview qgraphicsscene


【解决方案1】:

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

重要: xDatashort 是一个 QVector&lt;double&gt;,其中包括所有 x 值 yDatashort 是一个 QVector&lt;double&gt;,其中包括所有 y 值 两者都填充了 programm 类中的值,该类正在向连接发送信号,该连接启动插槽 drawGraph()

您也可以只使用QVector&lt;QPoint&gt;,这样更容易处理,但这不是我想要的。

lineVector 是一个QVector&lt;QGraphicsLineItem&gt;,它包含视图中的所有行

xScale 用于扩展情节,yScale 也是如此。

width 是协调系统的宽度 xAxisMark 是距离标记之间的像素距离 marksVector 是一个 QVector&lt;double&gt;,其中包含 x 轴的距离标记,应该是动态的

iCurrentVectorPoint 是一个运行时变量,它可以帮助我添加行。

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

如有其他问题,请发表评论,我会尽力帮助您在您的设备上获得精美的手工绘图。

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++;

}

【讨论】:

    【解决方案2】:

    更新:

    在 100 Hz 采样率和 20 Hz 帧率的情况下,代码可以稳定超过 50 分钟,可查看 800 个样本。对模拟器数据使用线程。随意问我关于这个话题的几乎所有事情,我研究了近 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);
    
    //    }
    
    }
    

    【讨论】:

      【解决方案3】:

      注意!! 这些解决方案不是最快的。使用 QPainterPath 而不是 QLineF,就像你拿一支笔,画一条线,把笔收起来,这样 1000 次。 最好保护 QPainterPath 中的所有 QPoints 并用笔一次绘制。这提高了实时绘图的性能,具有 4 分钟的趋势,甚至更长时间没有问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-18
        相关资源
        最近更新 更多