Results 1 to 11 of 11

Thread: QWidget::update() efficiency with hierarchy of custom widgets

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: QWidget::update() efficiency with hierarchy of custom widgets

    I will say what I'm usually saying in such cases. Do you really need to update 30 times per second? Plotting real-time data doesn't mean that plotting has to be real-time as well. Your eye won't manage to register any details of the plot at such frequency. Try dropping the framerate to 20Hz or even 16Hz and you should be fine. You can also have an adaptive timer that will increase frequency when more CPU power is available and reduce it when the load rises. This should make your app scale well for a different number of data sources.

    Also consider setting some flags for your widget, you should be able to optimize things a bit more.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  2. #2
    Join Date
    Dec 2010
    Posts
    35
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QWidget::update() efficiency with hierarchy of custom widgets

    Quote Originally Posted by wysota View Post
    I will say what I'm usually saying in such cases. Do you really need to update 30 times per second? Plotting real-time data doesn't mean that plotting has to be real-time as well. Your eye won't manage to register any details of the plot at such frequency. Try dropping the framerate to 20Hz or even 16Hz and you should be fine.
    You are correct here. We have tuned the refresh rate accordingly. I do have one instrument display, however, that is rather choppy looking at 16 - 20 frames/sec. It looks best at 25 - 30 frames/sec.
    You can also have an adaptive timer that will increase frequency when more CPU power is available and reduce it when the load rises. This should make your app scale well for a different number of data sources.
    I like that idea a lot.
    Also consider setting some flags for your widget, you should be able to optimize things a bit more.
    QWidget flags? Which ones?

    I also found another CPU hog with my display code, as well. I have a nice looking linear gradient for background of the main instrument panel, using QLinearGradient, the parameters of which are set in the central widget resize() method. That's what our screen designer wanted.....

    I found that no background reduced the CPU utilization dramatically - to about 10% on Linux when the overall instrument panel was maximized to full screen. That appears to be approaching QTimer overhead of the two timers I have. I'll see if i can use a static image instead for this and position it in the background according to the size of the overall instrument panel.

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: QWidget::update() efficiency with hierarchy of custom widgets

    Quote Originally Posted by redBeard View Post
    You are correct here. We have tuned the refresh rate accordingly. I do have one instrument display, however, that is rather choppy looking at 16 - 20 frames/sec. It looks best at 25 - 30 frames/sec.
    Are you reconstructing the path from scratch at every update?

    QWidget flags? Which ones?
    For example Qt::WA_OpaquePaintEvent and Qt::WA_StaticContents

    I also found another CPU hog with my display code, as well. I have a nice looking linear gradient for background of the main instrument panel, using QLinearGradient, the parameters of which are set in the central widget resize() method. That's what our screen designer wanted.....

    I found that no background reduced the CPU utilization dramatically - to about 10% on Linux when the overall instrument panel was maximized to full screen. That appears to be approaching QTimer overhead of the two timers I have. I'll see if i can use a static image instead for this and position it in the background according to the size of the overall instrument panel.
    Cache the background.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  4. #4
    Join Date
    Dec 2010
    Posts
    35
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QWidget::update() efficiency with hierarchy of custom widgets

    Quote Originally Posted by wysota View Post
    Are you reconstructing the path from scratch at every update?
    No. For the oscilloscope-type displays I have a QPainterPath of the range n domain axis lines which is only calculated when the display size changes. The actual data lines are an array of QLines. This is filled as the data arrives from an upstream flow element. The paintEvent() method just draws the one QPainterPath of axis lines and the drawLines() of the lines array (and, of course, setting the correct pen color).

    The jumpy display in question is an OpenGL-based graphic displaying FFT data (e.g., frequency analyzer). The vertices data never changes from refresh to refresh, just the colors. So I build the vertices buffer when the screen size changes. I cache the collection of color vectors and only recalculate the colors for new data when it arrives and 'memcopy' the old data to the new locations.

    Each refresh just consists of a single OpenGL call (glDrawElements()).
    For example Qt::WA_OpaquePaintEvent and Qt::WA_StaticContents
    I'll look at those.
    Cache the background.
    Here's the code for the background linear gradient:
    Qt Code:
    1. centralWidgetConstructor() {
    2. QLinearGradient backgroundGradient;
    3. backgroundGradient.setStart(), setFinalStop(), setColor()......
    4.  
    5. setBackgroundRole (QPalette::Window);
    6. QPalette p (palette());
    7. p.setBrush (QPalette::Window, QBrush (backgroundGradient));
    8. setPalette(p);
    9. }
    10. centralWidget::resize() {
    11. backgroundGradient.setFinalStop(width()/2, 0);
    12. QPalette p (palette());
    13. p.setBrush (QPalette::Window, QBrush (backgroundGradient));
    14. setPalette(p);
    15. }
    To copy to clipboard, switch view to plain text mode 
    The QLinearGradient is calculated when the screen size changes (which is not very often, typically when the display is first rendered. Users only rarely change the panel size).

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: QWidget::update() efficiency with hierarchy of custom widgets

    Quote Originally Posted by redBeard View Post
    No. For the oscilloscope-type displays I have a QPainterPath of the range n domain axis lines which is only calculated when the display size changes. The actual data lines are an array of QLines. This is filled as the data arrives from an upstream flow element. The paintEvent() method just draws the one QPainterPath of axis lines and the drawLines() of the lines array (and, of course, setting the correct pen color).
    Can you show us some code? I can immediately suggest an optimisation - if you append data to the path then you can cache parts of the path as pixmaps and only append the new chunks to the pixmap(s). Then drawing the plot boils down to rendering one or more pixmaps.

    The QLinearGradient is calculated when the screen size changes (which is not very often, typically when the display is first rendered. Users only rarely change the panel size).
    This doesn't do any graphics calculations or even colour calculations for the gradient. QLinearGradient is strictly a data carrier, nothing more. Your gradient is recalculated and redrawn upon every paint event. It's much better to render it once to a pixmap and then just blit the pixmap to the widget (with opaque paint event attribute set). In the end of all optimisations your paint event should be reduced to drawing at most three layers of pixmaps - the background, the plot and the foreground (grid). If you can combine the background and the foreground and draw the plot over the foreground, that's even better. Notice that with a GL paint engine this will be done by blitting three textures directly from the card's memory so it should be very fast.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Replies: 1
    Last Post: 22nd April 2010, 15:34
  2. Replies: 2
    Last Post: 22nd April 2010, 12:44
  3. Replies: 0
    Last Post: 15th May 2009, 16:38
  4. update() in QWidget
    By salmanmanekia in forum Qt Programming
    Replies: 5
    Last Post: 28th July 2008, 09:03
  5. QWidget::update() qeustion
    By tanki95 in forum Qt Programming
    Replies: 7
    Last Post: 14th March 2008, 03:29

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
  •  
Qt is a trademark of The Qt Company.