Results 1 to 10 of 10

Thread: Qwt: Is it possible to perform GUI operations from a separate QProcess?

  1. #1
    Join Date
    Dec 2020
    Posts
    4
    Thanks
    5
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Qwt: Is it possible to perform GUI operations from a separate QProcess?

    First of all, I am thinking the answer is no, but I cannot say for sure, so a confirmation would be nice.

    I am new to Qt and Qwt (and GUI programming in general), and I am relatively new to C++.
    I know you should not perform any GUI operations from a separate thread, but I was wondering if I could make something work using QProcess (or fork() obviously) and QSharedMemory, while still making it "feel" like one application.

    My goal is to build a GUI to display large amounts of data in real-time with Qt and Qwt. The GUI needs to contain 2 plots: the first plot needs to replot a completely new set of 1e6 samples for every update (needs to be done very quickly, minimum 10FPS), the second plot is a waterfall display (Google "fft waterfall display" if unfamiliar) based on the data of the first plot. My biggest concern is the speed of painting.

    If I only create the first plot, my GUI updates at about 17FPS.

    I am running my program on CentOS 7 with Qt 5.9.7 and Qwt 6.1.5.
    Last edited by seanj; 18th December 2020 at 17:03.

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Qwt: Is it possible to perform GUI operations from a separate QProcess?

    The restriction on multithreaded GUI operations is that GUI operations that paint to the screen must occur in the main thread. You can paint to QImage bitmaps from any thread and transfer them to the GUI thread for on-screen rendering. So in your case, if you can calculate and generate either or both of your images in separate threads, your main GUI thread only has to display them and that can be easily done at 10 fps.

    I am not sure where the actual QImage bits have to live - ie. whether the QImage has to be allocated in the main thread or whether it can be allocated in the thread that fills it. In any case, you should not perform your screen updates based on some QTimer or similar mechanism that establishes an update rate. Instead, you should use Qt's signal and slot mechanism to let the image creation thread tell the main thread that a new image is ready and to update the on-screen display. Otherwise, you run the risk of either wasting a lot of time in inappropriate polling or seeing glitches due to incompletely rendered images.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. The following user says thank you to d_stranz for this useful post:

    seanj (22nd December 2020)

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

    Default Re: Qwt: Is it possible to perform GUI operations from a separate QProcess?

    Quote Originally Posted by seanj View Post
    I am running my program on CentOS 7 with Qt 5.9.7 and Qwt 6.1.5.
    Better use Qwt 6.2 from SVN ( being released soon ) as it has a significant optimization ( QwtPlotCurve::FilterPointsAggressive ), that might be relevant for your usecase.

    Uwe

  5. The following user says thank you to Uwe for this useful post:

    seanj (22nd December 2020)

  6. #4
    Join Date
    Dec 2020
    Posts
    4
    Thanks
    5
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Qwt: Is it possible to perform GUI operations from a separate QProcess?

    Quote Originally Posted by d_stranz View Post
    In any case, you should not perform your screen updates based on some QTimer or similar mechanism that establishes an update rate. Instead, you should use Qt's signal and slot mechanism to let the image creation thread tell the main thread that a new image is ready and to update the on-screen display. Otherwise, you run the risk of either wasting a lot of time in inappropriate polling or seeing glitches due to incompletely rendered images.
    Currently, my first plot paints onto a widget still, but I plan on modifying my code to paint onto a QImage in a separate thread later on. Before I do that though, I am just curious, how could I use the signal and slot mechanism to notify when I am finished painting? Would I need to re-implement paintEvent and emit a signal after calling painter.end() ?

    Thank you, I greatly appreciate your help.


    Added after 4 minutes:


    Quote Originally Posted by Uwe View Post
    Better use Qwt 6.2 from SVN ( being released soon ) as it has a significant optimization ( QwtPlotCurve::FilterPointsAggressive ), that might be relevant for your usecase.

    Uwe
    Awesome! Thanks for the reply. I will check it out soon.
    How does this compare with QwtPlotCurve::FilterPoints? When I set QwtPlotCurve::FilterPoints to true, my frame rate drops from 16.5 FPS to 14.5 FPS.
    Last edited by seanj; 22nd December 2020 at 20:24.

  7. #5
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Qwt: Is it possible to perform GUI operations from a separate QProcess?

    how could I use the signal and slot mechanism to notify when I am finished painting?
    You're probably not going to have an actual paintEvent() in your thread, but instead you will have some other method that creates a new QImage with the current data. For whatever class it is that implements this updating, be sure it is derived from QObject (so it can emit signals), and implement a signal with a signature something like:

    Qt Code:
    1. signals:
    2.  
    3. void imageUpdated( const QImage & image );
    To copy to clipboard, switch view to plain text mode 

    In the GUI thread, add a slot to whatever QWidget class will display the image, and connect that slot to the thread's signal:

    Qt Code:
    1. public slots:
    2. void onImageUpdated( const QImage & image );
    To copy to clipboard, switch view to plain text mode 

    In that slot, copy the image, then call QWidget::update() to schedule a paintEvent().

    I am not familiar enough with the current state of Qwt to know how you would integrate this QImage-based rendering into a QwtPlot. Perhaps you would need to actually paint the entire QwtPlot into the QImage in your thread, or perhaps Qwt has a spectrogram-like plot where a QImage can be substituted for a calculated spectrogram.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  8. The following user says thank you to d_stranz for this useful post:

    seanj (23rd December 2020)

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

    Default Re: Qwt: Is it possible to perform GUI operations from a separate QProcess?

    Quote Originally Posted by seanj View Post
    How does this compare with QwtPlotCurve::FilterPoints?
    FilterPointsAggressive limits the maximum number of lines to be painted to: 4 * canvas.width() ( or height - depending on the orientation ).

    So if you have a line plot where the samples are ordered in x or y direction the effect will be very significant for 1e6 samples.
    If you have a scatter plot you could try what is done in the scatterplot example.

    HTH,
    Uwe

  10. The following user says thank you to Uwe for this useful post:

    seanj (23rd December 2020)

  11. #7
    Join Date
    Dec 2020
    Posts
    4
    Thanks
    5
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Qwt: Is it possible to perform GUI operations from a separate QProcess?

    Quote Originally Posted by d_stranz View Post
    You're probably not going to have an actual paintEvent() in your thread, but instead you will have some other method that creates a new QImage with the current data. For whatever class it is that implements this updating, be sure it is derived from QObject (so it can emit signals), and implement a signal with a signature something like:

    Qt Code:
    1. signals:
    2.  
    3. void imageUpdated( const QImage & image );
    To copy to clipboard, switch view to plain text mode 

    In the GUI thread, add a slot to whatever QWidget class will display the image, and connect that slot to the thread's signal:

    Qt Code:
    1. public slots:
    2. void onImageUpdated( const QImage & image );
    To copy to clipboard, switch view to plain text mode 

    In that slot, copy the image, then call QWidget::update() to schedule a paintEvent().
    Is it possible to implement similar functionality using the slot and signal mechanism if I am painting onto a widget, not a QImage? I attempted to do so, but when I run the program, no data is ever displayed on the plot.

    In plot constructor:

    Qt Code:
    1. connect(this, SIGNAL(plotUpdated()), this, SLOT(onPlotUpdated()));
    2.  
    3. d_timer = new QTimer(this);
    4.  
    5. d_timer->singleShot(10000, this, SLOT(onTimerFinished()));
    To copy to clipboard, switch view to plain text mode 

    onTimerFinished() slot, (added single shot timer and created this because I read that signals should be emitted inside an event):

    Qt Code:
    1. void Plot::onTimerFinished()
    2. {
    3. replot();
    4. Q_EMIT plotUpdated();
    5. }
    To copy to clipboard, switch view to plain text mode 

    onPlotUpdated() slot:

    Qt Code:
    1. void Plot::onPlotUpdated()
    2. {
    3. if (index < 10)
    4. {
    5. // update d_curve's data
    6. d_curve->updateSamples(index);
    7.  
    8. replot();
    9. index += 1;
    10. frame += 1;
    11.  
    12. // if index is 10, set to 0 to continue plotting
    13. if (index == 10) index = 0;
    14.  
    15. // stop the plotting
    16. if (frame > 1000)
    17. {
    18. // set index to 11 to stop plotting
    19. index = 11;
    20. }
    21. }
    22. Q_EMIT plotUpdated();
    23. }
    To copy to clipboard, switch view to plain text mode 

  12. #8
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Qwt: Is it possible to perform GUI operations from a separate QProcess?

    I read that signals should be emitted inside an event
    Don't know where you read this, but it is wrong. Signals can be emitted from any method. How they get handled depends on what type of signal/slot connection was made. See the documentation for QObject::connect().

    onPlotUpdated() slot:
    You realize you have set up an infinite loop here, right? You have connected the plotUpdated() signal to the onPlotUpdated() slot, and in that slot you emit the plotUpdated() signal, which calls the slot, which emits the signal, which calls the slot...

    d_timer->singleShot(10000, this, SLOT(onTimerFinished()));
    I don't have any idea what you are trying to do with this QTimer. And if all you want to do is call the onPlotUpdated slot, then make that the slot connected to the timer's timeout signal. No need to add a special slot that simply emits the plotUpdated signal.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  13. The following user says thank you to d_stranz for this useful post:

    seanj (28th December 2020)

  14. #9
    Join Date
    Dec 2020
    Posts
    4
    Thanks
    5
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Qwt: Is it possible to perform GUI operations from a separate QProcess?

    Quote Originally Posted by d_stranz View Post
    Don't know where you read this, but it is wrong. Signals can be emitted from any method. How they get handled depends on what type of signal/slot connection was made. See the documentation for QObject::connect().



    You realize you have set up an infinite loop here, right? You have connected the plotUpdated() signal to the onPlotUpdated() slot, and in that slot you emit the plotUpdated() signal, which calls the slot, which emits the signal, which calls the slot...



    I don't have any idea what you are trying to do with this QTimer. And if all you want to do is call the onPlotUpdated slot, then make that the slot connected to the timer's timeout signal. No need to add a special slot that simply emits the plotUpdated signal.
    1. I do not remember exactly, but I thought I read it in a Qt forum, I cannot find it anymore.

    2. I am aware of the infinite loop, my plan was to just add a counter variable and only emit the signal when the count is below a certain value.

    3. The sole reason I used a single shot timer is just so I could enter the event loop to emit a signal, but I now know that is not necessary.

    Thank you very much for the guidance, I really appreciate it.

  15. #10
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Qwt: Is it possible to perform GUI operations from a separate QProcess?

    Signals can be emitted from any method.
    A small correction - the method has to be a member of a class derived from QObject that contains the Q_OBJECT macro in its class definition, and the signal function itself must be declared as a signal in that class. Otherwise the MOC compiler won't generate the boilerplate code that defines the signal and integrates it into signal / slot connections. Typically signals are private or protected class methods that can't be called except from within their own classes.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. How to perform HSV Color mixing ?
    By Ashketchup in forum Qt Programming
    Replies: 1
    Last Post: 12th April 2012, 21:28
  2. Replies: 10
    Last Post: 30th January 2012, 12:01
  3. how to perform search in QTableWidget?
    By aurora in forum Qt Programming
    Replies: 3
    Last Post: 5th January 2012, 05:25
  4. Replies: 15
    Last Post: 24th December 2011, 13:07
  5. Problem with QProcess in two separate threads
    By viheaho in forum Qt Programming
    Replies: 2
    Last Post: 18th March 2010, 23:52

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.