Results 1 to 8 of 8

Thread: Real time plot doubts

  1. #1
    Join Date
    Mar 2017
    Posts
    7
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Real time plot doubts

    Hello, I'm new in this site, and I am not an expert programmer so, any help will be great for me

    I am creating a GUI, where in one graph, 6 signals are plotted, and in another graph, 6 other signals. example.png

    So these signals come from a serial port, and I need to graph them in real time and send them in real time.
    For now, I worry about the plotting part

    What I thought at first, was replot every time a new sample arrived, but I think this would be inefficient and I do not know if having 12 signals with approximately 2500 samples each, finish making the program slow.

    I was reading here, and found similar questions, I read the oscilloscope and real_time examples, but some parts do not become very clear to me.

    Probably you are already tired of responding to them, but I really still have doubts.

    I understand that:

    - I need to use a QVector for append new sample.
    - I need to set this samples to a QwtPlotCurve.
    - I need to use QwtPlotDirectPainter::drawSeries for draw only the las sample.

    Also need to use a QRect, but I dont understand well how this work.

    In the real_time example, I think the most important art is at incrementalplot.cpp rigth?

    but in the MainWindow.cpp file, never create and object of this class, only a randomplot object. I see that randomplot use the incrementalplot class and the method appendPoint (I think this is what I need), but I do not see the order in which the instructions are executed.

    In the oscilloscope example, something similar is used at plot.cpp specifically Plot::updateCurve().

    this, use a CurveData, that use a signaldata for append samples i think. (I think use a QVector for this rigth?).
    and after, the same of real_time: QwtScaleMap, QRect and QwtPlotDirectPainter::drawSeries. but this differs in that it verifies if it can write in the array before doing it, and if it is not possible, it saves in a buffer. Is this correct? I was never use QReadWriteLock so i dont know how it work.

    I have the same doubts as in the other example, I do not see the order in which the instructions are executed.

    But the principal question is how can I use the QwtPlotDirectPainter::drawSeries, why need to use a canvasMap and how use the QRect.

    Maybe are so many questions and maybe are trivials but, for me is a little difficult to understand.

    Any help will be greatly appreciated!

    I try with little examples using a qwtplot and 1 button, When I press the button, a new sample should be added:

    Qt Code:
    1. MainWindow::MainWindow(QWidget *parent) :
    2. QMainWindow(parent),
    3. ui(new Ui::MainWindow)
    4. {
    5. ui->setupUi(this);
    6. i=0; c = 0;
    7. ya = false;
    8. graf = new QwtPlotCurve("");
    9. graf->attach(ui->qwtPlot);
    10. d_directPainter = new QwtPlotDirectPainter();
    11.  
    12. }
    13.  
    14. void MainWindow::on_pushButton_clicked()
    15. {
    16. QPointF point = QPointF(c++,i);
    17. dat.append(point);
    18. graf->setSamples(dat);
    19.  
    20. xMap = ui->qwtPlot->canvasMap( graf->xAxis() );
    21. yMap = ui->qwtPlot->canvasMap( graf->yAxis() );
    22.  
    23. const QPointF center =
    24. QwtScaleMap::transform( xMap, yMap, point );
    25. r.moveCenter( center.toPoint() );
    26. clipRect += r;
    27.  
    28. d_directPainter->setClipRegion( clipRect );
    29.  
    30. d_directPainter->drawSeries( graf, dat.size() - 2, dat.size() - 1 );
    31.  
    32. if(!ya) {i++; if(i==10)ya=true;}
    33. else {i--; if(i==0)ya=false;}
    34. }
    To copy to clipboard, switch view to plain text mode 

    but this dont work. and try also:

    Qt Code:
    1. void MainWindow::on_pushButton_clicked()
    2. {
    3. QPointF point = QPointF(c++,i);
    4. dat.append(point);
    5. graf->setSamples(dat);
    6.  
    7. xMap = ui->qwtPlot->canvasMap( graf->xAxis() );
    8. yMap = ui->qwtPlot->canvasMap( graf->yAxis() );
    9.  
    10. const QSize symbolSize = graf->symbol()->size();
    11. QRect r( 0, 0, symbolSize.width() + 2, symbolSize.height() + 2 );
    12.  
    13. clipRect = QwtScaleMap::transform( xMap, yMap, br ).toRect();
    14. d_directPainter->setClipRegion( clipRect );
    15.  
    16. d_directPainter->drawSeries( graf, dat.size() - 2, dat.size() - 1 );
    17.  
    18. if(!ya) {i++; if(i==10)ya=true;}
    19. else {i--; if(i==0)ya=false;}
    20. }
    To copy to clipboard, switch view to plain text mode 

    But doesn't work either.

    Only with replot work for me

    Qt Code:
    1. QPointF point = QPointF(c++,i);
    2. dat.append(point);
    3. graf->setSamples(dat);
    4.  
    5. datos << QPointF(c++,i);
    6. graf->setSamples(datos);
    7. if(!ya) {i++; if(i==10)ya=true;}
    8. else {i--; if(i==0)ya=false;}
    9.  
    10. ui->qwtPlot->replot();
    To copy to clipboard, switch view to plain text mode 

    Thanks in advance, I hope someone can help me

    Here an image of how my interface is going, any comments or suggestions are also welcome

    gui.jpg

  2. #2
    Join Date
    Mar 2017
    Posts
    7
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Real time plot doubts

    Hello, im working in the code, and now I finally can plot in "real time" without reploting every time a sample arrive.

    I used the classes plot, curvedata and signaldata of the "Oscilloscope" example.

    The first time, I use the classes without reimplement nothing. This work fine in my "mini example", every time I had clicked the button, the graphic is plotting the sample =D.

    But this have one problem, create another plot over my original plot and even over the button: 1.jpg

    After resize a little for be able to click the button this is the result: 2.jpg

    So, you can see, the plot is over all and without layout.

    I want to use a QwtPlot that already exist, so I change a little the constructor of Plot:

    Qt Code:
    1. Plot::Plot( QwtPlot *parent ):
    2. // QwtPlot( parent ),
    3. d_paintedPoints( 0 ),
    4. d_interval( 0.0, 100000.0 ),
    5. d_timerId( -1 )
    6. {
    7. d_directPainter = new QwtPlotDirectPainter();
    8.  
    9. parent->setAutoReplot( false );
    10. parent->setCanvas( new Canvas() );
    11.  
    12. plotLayout()->setAlignCanvasToScales( true );
    13.  
    14. parent->setAxisTitle( QwtPlot::xBottom, "Time [s]" );
    15. parent->setAxisScale( QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue() );
    16. parent->setAxisScale( QwtPlot::yLeft, 0.0, 2000.0 );
    17.  
    18. QwtPlotGrid *grid = new QwtPlotGrid();
    19. grid->setPen( Qt::gray, 0.0, Qt::DotLine );
    20. grid->enableX( true );
    21. grid->enableXMin( true );
    22. grid->enableY( true );
    23. grid->enableYMin( false );
    24. grid->attach( parent );
    25.  
    26. d_origin = new QwtPlotMarker();
    27. d_origin->setLineStyle( QwtPlotMarker::Cross );
    28. d_origin->setValue( d_interval.minValue() + d_interval.width() / 2.0, 0.0 );
    29. d_origin->setLinePen( Qt::gray, 0.0, Qt::DashLine );
    30. d_origin->attach( parent );
    31.  
    32. d_curve = new QwtPlotCurve();
    33. d_curve->setStyle( QwtPlotCurve::Lines );
    34. d_curve->setPen( canvas()->palette().color( QPalette::WindowText ) );
    35. d_curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
    36. d_curve->setPaintAttribute( QwtPlotCurve::ClipPolygons, false );
    37. d_curve->setData( new CurveData() );
    38. d_curve->attach( parent );
    39. }
    To copy to clipboard, switch view to plain text mode 

    And I have this result: after_change.png

    But this have a problem, when I press the button the graphic dont plot nothing. First I was think this dont work, but after resize the window, the samples appear.

    So, the data only appear when I resize the window: after_resize.jpg

    If anyone can help me with this I will appreciate it very much

    I know maybe are stupid questions but Im not and expert programmer and some things are diffucult to understand for me.

    This is the MainWindow.cpp
    Qt Code:
    1. MainWindow::MainWindow(QWidget *parent) :
    2. QMainWindow(parent),
    3. ui(new Ui::MainWindow)
    4. {
    5. ui->setupUi(this);
    6. i=0; c = 0;
    7. d_plot = new Plot( ui->qwtPlot );
    8. // d_plot->setIntervalLength( 100000 );
    9.  
    10. }
    To copy to clipboard, switch view to plain text mode 

    And this is the click event:

    Qt Code:
    1. void MainWindow::on_pushButton_clicked()
    2. {
    3.  
    4. for(i=0;i<2000;i++){
    5. SignalData::instance().append( QPointF(c++,i) );
    6. d_plot->updateCurve();
    7. }
    8.  
    9. }
    To copy to clipboard, switch view to plain text mode 

    Thank you again =)

    Regards

  3. #3
    Join Date
    Mar 2017
    Posts
    7
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Real time plot doubts

    Hello, I finally could solve the problem

    I reimplemented the Plot class and now, it is no longer a class derived from QwtPlot.

    Now I will show you the files in case in the future someone is presented with the same doubt as me:

    Plot.h
    Qt Code:
    1. class Plot
    2. {
    3.  
    4. public:
    5. Plot(QwtPlot * = NULL );
    6. ~Plot();
    7.  
    8. void replot();
    9.  
    10. void updateCurve();
    11.  
    12. void setXinterval( double min, double max );
    13.  
    14. void setYinterval( double min, double max );
    15.  
    16. void setPen(const QColor &color, qreal width=0.0, Qt::PenStyle style = Qt::SolidLine);
    17.  
    18.  
    19. private:
    20.  
    21.  
    22. QwtPlot *plot;
    23.  
    24. QwtPlotCurve *d_curve;
    25. int d_paintedPoints;
    26.  
    27. QwtPlotDirectPainter *d_directPainter;
    28.  
    29. QwtInterval x_interval;
    30. QwtInterval y_interval;
    31.  
    32. };
    To copy to clipboard, switch view to plain text mode 

    Plot.cpp
    Qt Code:
    1. #include "plot.h"
    2. #include "curvedata.h"
    3. #include "signaldata.h"
    4. #include <qwt_plot_canvas.h>
    5. #include <qwt_plot_marker.h>
    6. #include <qwt_plot_curve.h>
    7. #include <qwt_plot_directpainter.h>
    8. #include <qwt_curve_fitter.h>
    9. #include <qwt_painter.h>
    10.  
    11. class Canvas: public QwtPlotCanvas
    12. {
    13. public:
    14. Canvas( QwtPlot *plot = NULL ):
    15. QwtPlotCanvas( plot )
    16. {
    17. // The backing store is important, when working with widget
    18. // overlays ( f.e rubberbands for zooming ).
    19. // Here we don't have them and the internal
    20. // backing store of QWidget is good enough.
    21.  
    22. setPaintAttribute( QwtPlotCanvas::BackingStore, false );
    23. setBorderRadius( 10 );
    24.  
    25. if ( QwtPainter::isX11GraphicsSystem() )
    26. {
    27. #if QT_VERSION < 0x050000
    28. // Even if not liked by the Qt development, Qt::WA_PaintOutsidePaintEvent
    29. // works on X11. This has a nice effect on the performance.
    30.  
    31. setAttribute( Qt::WA_PaintOutsidePaintEvent, true );
    32. #endif
    33.  
    34. // Disabling the backing store of Qt improves the performance
    35. // for the direct painter even more, but the canvas becomes
    36. // a native window of the window system, receiving paint events
    37. // for resize and expose operations. Those might be expensive
    38. // when there are many points and the backing store of
    39. // the canvas is disabled. So in this application
    40. // we better don't disable both backing stores.
    41.  
    42. if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) )
    43. {
    44. setAttribute( Qt::WA_PaintOnScreen, true );
    45. setAttribute( Qt::WA_NoSystemBackground, true );
    46. }
    47. }
    48.  
    49. }
    50.  
    51. };
    52.  
    53. Plot::Plot( QwtPlot *parent ):
    54. plot( parent ),
    55. d_paintedPoints( 0 ),
    56. x_interval( 0.0, 100000.0 ),
    57. y_interval( 0.0, 2000.0 )
    58. {
    59. d_directPainter = new QwtPlotDirectPainter();
    60.  
    61. plot->setAutoReplot( false );
    62. plot->setCanvas( new Canvas() );
    63.  
    64. plot->setAxisScale( QwtPlot::xBottom, x_interval.minValue(), x_interval.maxValue() );
    65. plot->setAxisScale( QwtPlot::yLeft, y_interval.minValue(), y_interval.maxValue() );
    66.  
    67. d_curve = new QwtPlotCurve();
    68. d_curve->setStyle( QwtPlotCurve::Lines );
    69. // d_curve->setPen( plot->canvas()->palette().color( QPalette::WindowText ) );
    70. d_curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
    71. d_curve->setPaintAttribute( QwtPlotCurve::ClipPolygons, false );
    72. d_curve->setData( new CurveData() );
    73. d_curve->attach( plot );
    74. }
    75.  
    76. Plot::~Plot()
    77. {
    78. delete d_directPainter;
    79. }
    80.  
    81.  
    82.  
    83. void Plot::replot()
    84. {
    85. CurveData *data = static_cast<CurveData *>( d_curve->data() );
    86. data->values().lock();
    87.  
    88. plot->replot();
    89. d_paintedPoints = data->size();
    90.  
    91. data->values().unlock();
    92. }
    93.  
    94. void Plot::setXinterval( double min, double max )
    95. {
    96. x_interval.setMaxValue( max );
    97. x_interval.setMinValue( min );
    98. plot->setAxisScale( QwtPlot::xBottom,
    99. x_interval.minValue(), x_interval.maxValue() );
    100.  
    101. replot();
    102. }
    103.  
    104. void Plot::setYinterval( double min, double max )
    105. {
    106. y_interval.setMaxValue( max );
    107. y_interval.setMinValue( min );
    108. plot->setAxisScale( QwtPlot::yLeft,
    109. y_interval.minValue(), y_interval.maxValue() );
    110.  
    111. replot();
    112. }
    113.  
    114. void Plot::setPen(const QColor &color, qreal width, Qt::PenStyle style)
    115. {
    116. d_curve->setPen(color, width, style);
    117. }
    118.  
    119. void Plot::updateCurve()
    120. {
    121. CurveData *data = static_cast<CurveData *>( d_curve->data() );
    122. data->values().lock();
    123.  
    124. const int numPoints = data->size();
    125. if ( numPoints > d_paintedPoints )
    126. {
    127. const bool doClip = !plot->canvas()->testAttribute( Qt::WA_PaintOnScreen );
    128. if ( doClip )
    129. {
    130. /*
    131.   Depending on the platform setting a clip might be an important
    132.   performance issue. F.e. for Qt Embedded this reduces the
    133.   part of the backing store that has to be copied out - maybe
    134.   to an unaccelerated frame buffer device.
    135.   */
    136.  
    137. const QwtScaleMap xMap = plot->canvasMap( d_curve->xAxis() );
    138. const QwtScaleMap yMap = plot->canvasMap( d_curve->yAxis() );
    139.  
    140. QRectF br = qwtBoundingRect( *data,
    141. d_paintedPoints - 1, numPoints - 1 );
    142.  
    143. const QRect clipRect = QwtScaleMap::transform( xMap, yMap, br ).toRect();
    144. d_directPainter->setClipRegion( clipRect );
    145. }
    146.  
    147. d_directPainter->drawSeries( d_curve,
    148. d_paintedPoints - 1, numPoints - 1 );
    149. d_paintedPoints = numPoints;
    150. }
    151.  
    152. data->values().unlock();
    153. }
    To copy to clipboard, switch view to plain text mode 

    The curvedata.h, curvedata.cpp, signaldata.h and signaldata.cpp are the same of the ocsilloscope example.

    You need to copy this files on your project.

    For append data only need to use the command:
    Qt Code:
    1. SignalData::instance().append( QPointF value ); // where value is your data to append
    To copy to clipboard, switch view to plain text mode 

    For plot:
    Qt Code:
    1. updateCurve();
    To copy to clipboard, switch view to plain text mode 

    I only have one doubt now, if I want to plot more than 1 signal in the same QwtPlot, how can I make this?

    I hope I can be of help to some =)

    And hope than someone can help me with this doubt. Thank you

  4. #4
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,311
    Thanked 879 Times in 827 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Real time plot doubts

    It's always hard to say something useful, when questions are too complex, where I would need to see/check lot of code - sorry for not being responsive.
    Considering your final question: of course you can have as many signals as you want to. All you need to do is to use one curve per signal.

    Uwe

  5. #5
    Join Date
    Mar 2017
    Posts
    7
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Real time plot doubts

    Hello, thanks for answer

    How can I do that? I tried declaring 2 curvedata objects and 2 plot object, but when I plot the signals, it is like if I had only one datacurve and one "plot" object, and is like if I append the data of both signals in the same curve. Is a disaster when is plotting.

    Thanks again

  6. #6
    Join Date
    Mar 2017
    Posts
    7
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Real time plot doubts

    To be more specific this is what I did:

    Qt Code:
    1. d1 = new CurveData;
    2. d2 = new CurveData;
    3.  
    4. d_plot = new Plot( ui->qwtPlot );
    5. p2 = new Plot( ui->qwtPlot );
    6.  
    7. for(i=0;i<2000;i++){
    8. d1->values().append( QPointF(c++,i) );
    9. d_plot->updateCurve();
    10. d2->values().append( QPointF(c+50000,2000-i) );
    11. p2->updateCurve();
    12. }
    To copy to clipboard, switch view to plain text mode 

    But I was unlucky. This is the result:bad_result.png

    And that's how it should be:good_result.png

    The red lines are the signals.

    Any suggestions?

  7. #7
    Join Date
    Mar 2017
    Posts
    7
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Real time plot doubts

    Hello, I disappeared a while because I was a little busy.

    Maybe I do not need to use the SignalData like a Static type?

    I dont understand how this work very well. Any one can help me?

    I still can not graph more than one signal in real time in the same QwtPlot.

    Please help me with that =(

  8. #8
    Join Date
    Mar 2017
    Posts
    7
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Real time plot doubts

    Finally i was able to solve the problem =D

    I just copy the classes plot, curvedata and signaldata, and rename them.

    This is the code:

    MainWindow:
    Qt Code:
    1. MainWindow::MainWindow(QWidget *parent) :
    2. QMainWindow(parent),
    3. ui(new Ui::MainWindow)
    4. {
    5. ui->setupUi(this);
    6. i=0; c = 0;
    7.  
    8. d1 = new CurveData;
    9. d2 = new CurveData_copy;
    10.  
    11. d_plot = new Plot( ui->qwtPlot );
    12. p2 = new Plot_copy( ui->qwtPlot );
    13. p2->setPen(Qt::blue,1.0);
    14.  
    15. }
    To copy to clipboard, switch view to plain text mode 

    Button event:
    Qt Code:
    1. void MainWindow::on_pushButton_clicked()
    2. {
    3. for(i=0;i<2000;i++){
    4.  
    5. d1->values().append( QPointF(c++,i) );
    6. d_plot->updateCurve();
    7. d2->values().append( QPointF(c+50000,2000-i) );
    8. p2->updateCurve();
    9.  
    10. }
    11.  
    12. }
    To copy to clipboard, switch view to plain text mode 

    The "problem" is that I need to use 12 signals, and I dont know if this is the most "efficient" method.

    Any suggestion is welcome =)

    Here a picture of the result: 2curves.png

    I hope i can help someone with this. =)

Similar Threads

  1. How to real time plot?
    By RafaelRSE in forum Qwt
    Replies: 2
    Last Post: 7th August 2014, 18:14
  2. Replies: 3
    Last Post: 12th April 2013, 06:18
  3. How to plot real time x/y graph in Qtopia
    By desperado_43 in forum Qt for Embedded and Mobile
    Replies: 0
    Last Post: 18th May 2012, 08:00
  4. real time graph plot
    By robotics in forum Qt Programming
    Replies: 5
    Last Post: 24th May 2011, 05:04
  5. QFileSystemWatcher with a Qwt Real-time plot
    By gen_mass in forum Qt Programming
    Replies: 1
    Last Post: 25th June 2010, 21:28

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.