Results 1 to 7 of 7

Thread: QwtPlot::replot() won't clear current plot

  1. #1
    Join Date
    Mar 2014
    Posts
    11
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11

    Default QwtPlot::replot() won't clear current plot

    Hello!

    For a few hours I've been scratching my head about what seems to be a simple problem. What I want my application to do is that I want to collect sensor data and plot them. I'm running my application on a Raspberry PI so I tested to use the SetRawSamples() method, which worked but was to slow on some screens. What I want to do instead is something similar to the oscilloscope example where they use QwtPlotDirectPainter instead, even though I've not been able to test the performance of the application in it's final state I found out that it was fast enough for my needs.

    So, what my application is doing right now:
    1. Store 10 sensor values in CurveData
    2. Draw a curve segment of the 10 latest values
    3. Repeat 100 times until 1000 values are plotted
    4. Return to the left side of the plot and continue with plotting segments, thus drawing a new curve over the existing one


    Here is an image of the result:
    2014-03-17 16.54.57.jpg

    Now, what I want to do is to clear my current plot when 1000 values are plotted and only see 1 curve in my plot window. I'm currently calling QwtPlot::replot() when I clear my curve data but it still wont clear the plot.

    This is my plot.cpp file in it's current state:
    Qt Code:
    1. #include "plot.h"
    2. #include <qwt_plot.h>
    3. #include <qwt_plot_grid.h>
    4. #include <qwt_plot_layout.h>
    5. #include <qwt_plot_canvas.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 CurveData: public QwtArraySeriesData<QPointF>
    12. {
    13. public:
    14. CurveData()
    15. {
    16. }
    17.  
    18. virtual QRectF boundingRect() const
    19. {
    20. if ( d_boundingRect.width() < 0.0 )
    21. d_boundingRect = qwtBoundingRect( *this );
    22.  
    23. return d_boundingRect;
    24. }
    25.  
    26. inline void append( const QPointF &point )
    27. {
    28. d_samples += point;
    29. }
    30.  
    31. void clear()
    32. {
    33. d_samples.clear();
    34. d_samples.squeeze();
    35. d_boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 );
    36. }
    37. };
    38.  
    39. Plot::Plot( QWidget *parent ):
    40. QwtPlot( parent )
    41. {
    42. d_directPainter = new QwtPlotDirectPainter(this);
    43.  
    44. setAutoReplot(false);
    45.  
    46. setAxisTitle(QwtPlot::xBottom, "Time [s]");
    47. setAxisScale(QwtPlot::yLeft, 0.014,0.016);
    48. setAxisScale(QwtPlot::xBottom, 0, 1000);
    49.  
    50. d_curve = new QwtPlotCurve();
    51. d_curve->setData(new CurveData());
    52. d_curve->attach(this);
    53. }
    54.  
    55. Plot::~Plot()
    56. {
    57. delete d_directPainter;
    58. }
    59.  
    60. void Plot::AppendPoint(const QPointF &point)
    61. {
    62. CurveData *data = static_cast<CurveData *>(d_curve->data());
    63. data->append(point);
    64. }
    65.  
    66. void Plot::DrawCurveSegment()
    67. {
    68. CurveData *data = static_cast<CurveData *>(d_curve->data());
    69.  
    70. d_directPainter->drawSeries(d_curve, data->size()-11, data->size()-1);
    71. }
    72.  
    73. void Plot::ClearPlot()
    74. {
    75. d_curve->setData(new CurveData());
    76. QwtPlot::replot();
    77. }
    To copy to clipboard, switch view to plain text mode 

    And here is the interesting parts of my mainwindow.cpp
    Qt Code:
    1. #include "mainwindow.h"
    2. #include "plot.h"
    3. #include <QtWidgets>
    4.  
    5. MainWindow::MainWindow(QWidget *parent):
    6. QWidget( parent )
    7. {
    8. d_plot = new Plot(this);
    9. counter = 0;
    10. loopCounter = 0;
    11.  
    12. // ... //
    13.  
    14. connect(generateButton, SIGNAL(clicked()), this, SLOT(generate()));
    15.  
    16. // ... //
    17. }
    18.  
    19. void MainWindow::generate()
    20. {
    21. (void)startTimer(50);
    22. }
    23.  
    24. void MainWindow::timerEvent(QTimerEvent *) {
    25. if (counter>0 && counter%1000==0)
    26. {
    27. d_plot->ClearPlot();
    28. loopCounter++;
    29. }
    30.  
    31. for (int ii=0; ii<10;ii++)
    32. {
    33. double y = sensorVals[counter];
    34. double x = (double)counter-((double)loopCounter*1000);
    35.  
    36. counter++;
    37. d_plot->AppendPoint(QPointF(x,y));
    38. }
    39. d_plot->DrawCurveSegment();
    40. }
    To copy to clipboard, switch view to plain text mode 

    Would appreciate any help, also please let me know if any information in my post is missing.

    Best regards!

  2. #2
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,218
    Thanked 850 Times in 799 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QwtPlot::replot() won't clear current plot

    Hm, your code uses the direct painter in the same cycle as the replot - there was a bug report indicating that the paint region of the replot gets swallowed by the internal pain event generated by the direct painter. Maybe this is the case in your application too ( don't see any obvious bug ). I would be interested in investigating in this issue - could you please upload a small compilable demo ?

    For your type of application I would recommend to go with Qt4 ( not Qt5 ) enabling the X11 paintengine ( graphicssystem: native ). Only this way you might see hardware accelerated graphics and the direct painter is more effective as it doesn't need to send dummy paint events ( what probable are the reason for the issue above ).

    Then initialize your canvas this way:

    Qt Code:
    1. QwtPlotCanvas *canvas = new QwtPlotCanvas();
    2. canvas->setPaintAttribute( QwtPlotCanvas::BackingStore, false );
    3. canvas->setAttribute( Qt::WA_PaintOutsidePaintEvent, true );
    4.  
    5. plot->setCanvas( canvas );
    To copy to clipboard, switch view to plain text mode 

    You could also play with:

    Qt Code:
    1. canvas->setAttribute( Qt::WA_PaintOnScreen, true );
    2. canvas->setAttribute( Qt::WA_NoSystemBackground, true );
    To copy to clipboard, switch view to plain text mode 
    Uwe

  3. #3
    Join Date
    Mar 2014
    Posts
    11
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: QwtPlot::replot() won't clear current plot

    Quote Originally Posted by Uwe View Post
    Hm, your code uses the direct painter in the same cycle as the replot - there was a bug report indicating that the paint region of the replot gets swallowed by the internal pain event generated by the direct painter. Maybe this is the case in your application too ( don't see any obvious bug ). I would be interested in investigating in this issue - could you please upload a small compilable demo ?

    For your type of application I would recommend to go with Qt4 ( not Qt5 ) enabling the X11 paintengine ( graphicssystem: native ). Only this way you might see hardware accelerated graphics and the direct painter is more effective as it doesn't need to send dummy paint events ( what probable are the reason for the issue above ).

    Then initialize your canvas this way:

    Qt Code:
    1. QwtPlotCanvas *canvas = new QwtPlotCanvas();
    2. canvas->setPaintAttribute( QwtPlotCanvas::BackingStore, false );
    3. canvas->setAttribute( Qt::WA_PaintOutsidePaintEvent, true );
    4.  
    5. plot->setCanvas( canvas );
    To copy to clipboard, switch view to plain text mode 

    You could also play with:

    Qt Code:
    1. canvas->setAttribute( Qt::WA_PaintOnScreen, true );
    2. canvas->setAttribute( Qt::WA_NoSystemBackground, true );
    To copy to clipboard, switch view to plain text mode 
    Uwe
    Hi!

    I dont really know what the advantage and the disadvantages is between Qt4 and Qt5 but it took me a good while to get Qt5 up and running on the RPI so I would prefer to avoid all that hazzle again. The thing that confuses me is that I have got the qwt realtime and qwt oscilloscope example up and running and they work flawlessly. And they do pretty much what I want to do, however, those example are able to replot so it leads me to think that somewhere in my code there is an error.

    I have attached a compilable example to this post, the only difference between the example and the project I attached in the OP is that random numbers are generated instead of reading values from a file, the file was to big to be attached if I used the original project.

    qwtTest.zip

    Also tested the suggestions you had in your reply but it didn't work.

    And lastly, please note that I cross compile the project to my RPI so you may have to change the project file.

    Best regards!

  4. #4
    Join Date
    Mar 2014
    Posts
    11
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: QwtPlot::replot() won't clear current plot

    A small update, I somehow got the clearPlot() method to work but I don't know if I've solved it in an "incorrect way".

    I changed my clearPlot() method to the following:
    Qt Code:
    1. void Plot::ClearPlot()
    2. {
    3. CurveData *data = static_cast<CurveData *>(d_curve->data());
    4. data->clear();
    5.  
    6. QwtPlot::replot();
    7. QwtPlot::repaint();
    8. }
    To copy to clipboard, switch view to plain text mode 

    I have to call replot and then I have to call repaint as well. Does anyone know why it works when I do it like this?

  5. #5
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,218
    Thanked 850 Times in 799 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QwtPlot::replot() won't clear current plot

    Quote Originally Posted by Mindstormer View Post
    I dont really know what the advantage and the disadvantages is between Qt4 and Qt5 but it took me a good while to get Qt5 up and running on the RPI so I would prefer to avoid all that hazzle again.
    Sure but as you are on a Pi where you have a very weak CPU and your question is about performance it is worth to understand your options:

    There are to paint engines available for Qt/X11:


    • raster
    • x11


    The raster paint engine is a pure software renderer, what means the lines of a curve are calculated pixel by pixel by the CPU. The X11 paintengine is using the Xlib for rendering lines, what would be done by the graphics hardware, when you have X11 drivers on your system, that support hardware acceleration. Qt4 offers both paint engines and you can decide which one to use. For Qt <= 4.7 X11 is the default, but for Qt4.8 raster has been made the default. In Qt5 only the raster paint engine is available.

    But even, when going with raster you should disable the backing store of the canvas for something like a oscilloscope. It doubles what the software renderer has to do, while you never use widget overlays on the canvas ( f.e the rubberband of the zoomer ), where the backing store is of interest.

    I remember running the oscilloscope example on the Pi at about 20% CPU load.

    The thing that confuses me is that I have got the qwt realtime and qwt oscilloscope example up and running and they work flawlessly. And they do pretty much what I want to do, however, those example are able to replot so it leads me to think that somewhere in my code there is an error.
    No this should be the Qwt issue I was talking about in my previous mail. You can avoid it by setting QwtPlotCanvas::ImmediatePaint to true, what has the effect, that the replot calls repaint instead of update.

    Uwe

  6. #6
    Join Date
    Mar 2014
    Posts
    11
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: QwtPlot::replot() won't clear current plot

    Thanks for your help Uwe, much apreciated!

    Quote Originally Posted by Uwe View Post
    I remember running the oscilloscope example on the Pi at about 20% CPU load.
    Which QT version was that? I just checked my CPU usage on my pi and it was 20-25% with QT5.

  7. #7
    Join Date
    Feb 2006
    Location
    Munich, Germany
    Posts
    3,218
    Thanked 850 Times in 799 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QwtPlot::replot() won't clear current plot

    Not 100% sure but AFAIR it was an earlier Version of Raspbian running Qwt 6.1 with Qt4 ( using X11 paint engine ). But when using X11 much of the work is done in the X Server what needs to be taken into count, when comparing systems.

    I recommend simply to install Qt4 on your system and build Qwt for it ( maybe there are precompiled packages available ? ) . Then you can compare the oscilloscope example running it with raster or x11: see .http://qt-project.org/doc/qt-4.8/qap...GraphicsSystem

Similar Threads

  1. the replot of a qwtPlot is too slow
    By gaia86 in forum Qwt
    Replies: 3
    Last Post: 4th April 2012, 09:33
  2. the replot of a qwtPlot is too slow
    By gaia86 in forum Qwt
    Replies: 1
    Last Post: 3rd April 2012, 17:54
  3. the replot of a qwtPlot is too slow
    By gaia86 in forum Qwt
    Replies: 0
    Last Post: 3rd April 2012, 16:19
  4. Replies: 1
    Last Post: 4th November 2009, 23:14
  5. Replies: 15
    Last Post: 26th October 2009, 19:47

Tags for this Thread

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.