2017-05-04 3 views
1

Je développe actuellement un petit programme en Qt. Pour afficher un graphique, vous pouvez utiliser qwt ou qcustomplot ou le qpainterevent ou QChart. Mais je suis interessé dans une solution pour un tracé dynamique qui est écrit avec le QGraphicsView.Qt | Création d'un graphique/tracé dynamique avec QGraphicsView, Scène QGraphics | données en temps réel

Mes préférences -width de mon tableau doivent être -realtime constante tracé -le premier échantillon doit être supprimé ou overwriten si la fin du graphique est atteint, il est donc un tableau dynamique et fluide

Mon exemple ci-dessous est capable d'être dynamique et fluide ... mais juste pour le nombre, qui est dans ma clause if. Je ne comprends pas pourquoi. L'idée est de supprimer le premier élément, donc j'ai constamment 99 éléments. Si je supprime un élément, je veux donner à l'élément suivant la position de l'élément avant. Alors x = 99 sera x = 98 ...... x = 1 sera x = 0;

Est-ce que j'ai une erreur dans mon idée? J'ai aussi eu plusieurs idées, mais c'est probablement le meilleur.

Merci à l'avance Konrad

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

Vous pourriez me expliquer mieux. – eyllanesc

+0

Où avez-vous besoin d'une meilleure explication? En ce que je veux de ce que j'ai codé? –

Répondre

0

ATTENTION !! Ces solutions ne sont pas les plus rapides les. Utilisez QPainterPath au lieu de QLineF, c'est comme si vous prenez un stylo, tracez une ligne, mettez le stylo à l'écart, et cela 1000 fois. Mieux vaut sûr tous Qpoints dans un QPainterPath et prendre une fois que le stylet pour dessiner. Cela augmente la performance à Realtime Plotting avec une tendance de 4 min et plus sans problèmes.

1

Jusqu'à présent, thats la meilleure réponse, faites attention que si vous utilisez 100Hz comme échantillonage, ma performance est juste stable avec 50 samplesInView. Vous pouvez réduire le taux d'échantillonnage et augmenter le nombre d'échantillons pour avoir plus de valeurs dans le tracé.

Important: xDatashort est un QVector<double> qui comprend toutes les valeurs x yDatashort est un QVector<double> qui inclut toutes les valeurs y les deux sont remplis avec des valeurs dans la classe programm, cette classe émet le signal de la connexion qui démarre la fente drawGraph().

Vous pouvez aussi utiliser un QVector<QPoint> ce qui le rend plus facile à manipuler, mais ce ne est pas ce que je veux dans mon cas.

lineVector est un QVector<QGraphicsLineItem> qui toutes les lignes inclues de la vue

xScale est utilisé pour prolonger la parcelle, yScale ainsi.

width est la largeur de la Coordinationsystem xAxisMark est le pixeldistance entre les marques de distance marksVector est un QVector<double> qui comprend les marques de distance de l'axe x, qui doit être dynamique

iCurrentVectorPoint est un runtimevariable, ce qui contribue moi d'ajouter les lignes.

!! Ce code est bon à utiliser pour le traçage en temps réel, mais il n'a pas les meilleures performances, donc si quelqu'un a des idées pour libérer le potentiel, n'hésitez pas à obtenir la meilleure réponse :) !!

Pour des questions d'autres commentaires et je ne vais essayer de vous aider à obtenir un beau terrain à la main sur votre appareil.

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

} 
0

Mise à jour:

code stable pendant plus de 50 min avec 800 échantillons en vue, avec 100 Hz et 20 Hz samplerate framerate. En utilisant un fil pour le simulatordata. Ne hésitez pas à me demander presque tout sur ce sujet, je travaillais à travers elle pendant près de 2 mois: 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); 

// } 

}