Results 1 to 6 of 6

Thread: QGraphicsScene and QThread

  1. #1
    Join Date
    Jan 2007
    Posts
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default QGraphicsScene and QThread

    Hi all,

    I am using QGraphicsScene and QGraphicsView for rendering 2D graphics of vehicle traffic simulation. I want user to be able to control the simulation (i.e. start, stop and pause) so I assume QThread is required to prevent the GUI from freezing while the system does all the computation for the simulation.

    I was wondering if it is a good idea to actually share the scene data between QGraphicsView and QThread subclasses. Will there be any complication in situation where QGraphicsView is redrawing while QThread tries to update the scene? Would it be safer to somehow render my scene to a QImage then draw the image instead? Hope someone can advice on this. Thanks.


    Thuan Seah Tan

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

    Default Re: QGraphicsScene and QThread

    Quote Originally Posted by tts80 View Post
    I am using QGraphicsScene and QGraphicsView for rendering 2D graphics of vehicle traffic simulation. I want user to be able to control the simulation (i.e. start, stop and pause) so I assume QThread is required to prevent the GUI from freezing while the system does all the computation for the simulation.
    Not necessarily. You can divide the computation into steps and use a timer with 0 timeout to trigger slots which will do the computation. This way you won't block the event queue and will be able to do everything in one thread. Alternatively you can use QCoreApplication::processEvents() to force event processing during a complex operation.

    I was wondering if it is a good idea to actually share the scene data between QGraphicsView and QThread subclasses.
    Definitely not. You'll run into synchronisation problems.

    Will there be any complication in situation where QGraphicsView is redrawing while QThread tries to update the scene? Would it be safer to somehow render my scene to a QImage then draw the image instead? Hope someone can advice on this. Thanks.
    It would be best to avoid using the thread at all

  3. #3
    Join Date
    Apr 2006
    Posts
    29
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: QGraphicsScene and QThread

    Hello,

    Tts80 adressed TMO a very interesting problem. I also need to implement some kind of "deamons" in my application. By deamon, I mean a piece of code running in background to maintain a datastructure according to the user interaction.

    This requirement led me to implement these algorithms as threads. Of course, the thread has to deal with objects inheriting QObject that are reentrant but also to interact with GUI elements which are not reentrant. Of course I have problems when the thread interacts with widgets but I've not yet understood what really is the problem in using widgets in threads (I think the Trolls documentation is not explicit enough about that). Moreover, the nature of these problems vary, depending on the platform I'm using (MacOSX or Ubuntu ...). Another point that led me to the design of threads is that these computations might be quite heavy, I do not want to freeze the application during them.

    QCoreApplication:rocessEvents() processes all pending events according to the specified flags until there are no more events to process. Does it actually postpone a computation using a priority queue ?

    So Wysota, you suggest a general workaround to replace threads ? Could you give us a short example ? In which case do you suggest using threads (except for network stuff of course), in which case do you suggest to avoid using threads ?

    Thanks, Julien.

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

    Default Re: QGraphicsScene and QThread

    Quote Originally Posted by jwintz View Post
    Of course I have problems when the thread interacts with widgets but I've not yet understood what really is the problem in using widgets in threads
    You may be accessing internal QWidget data from within two different threads trashing it effectively.

    QCoreApplication:rocessEvents() processes all pending events according to the specified flags until there are no more events to process. Does it actually postpone a computation using a priority queue ?
    No, it simply calls the event queue and processes it. You might say that when you call QApplication::exec() its implementation (of course this is a simplification!) looks like:
    Qt Code:
    1. while(!end) processEvents();
    To copy to clipboard, switch view to plain text mode 

    So Wysota, you suggest a general workaround to replace threads ?
    Only when it's appropriate

    Could you give us a short example ?
    I can. Imagine you want to generate a large amount of random numbers and spit it out in your app. In a non-GUI app you would simply do:

    Qt Code:
    1. int main(){
    2. for(int i=0;i<10000;i++)
    3. printf("%d\n", rand());
    4. return 0;
    5. }
    To copy to clipboard, switch view to plain text mode 

    In a GUI app you do the same, just redirect the output to some widget. The problem is that it blocks the application until the loop exits.

    So an obvious workaround is to use threads:

    Qt Code:
    1. class MyThread : public QThread {
    2. Q_OBJECT
    3. public:
    4. MyThread(QTextEdit *edit, QObject *parent=0) : QThread(parent){
    5. connect(this, SIGNAL(generated(const QString &)), edit, SLOT(append(const QString &)));
    6. }
    7. void run(){
    8. for(int i=0;i<10000;i++)
    9. emit generated(QString::number(rand()));
    10. }
    11. signals:
    12. void generated(const QString &);
    13. };
    14.  
    15. int main(int argc, char **argv){
    16. QApplication app(argc, argv);
    17. MyThread thread(&te, &app);
    18. thread.start();
    19. return app.exec();
    20. }
    To copy to clipboard, switch view to plain text mode 

    This should work as expected, but there is really no point in using the worker thread as you can achieve the same by:

    Qt Code:
    1. class Dummy : public QObject {
    2. Q_OBJECT
    3. public:
    4. Dummy() : QObject(){ cnt = 0; }
    5. void start(){
    6. QTimer::singleShot(0, this, SLOT(generate()));
    7. }
    8. public slots:
    9. void generate(){
    10. emit generated(QString::number(rand()));
    11. if(++cnt<10000)
    12. QTimer::singleShot(0, this, SLOT(generate())); // "schedule" next timeout immediately
    13. }
    14. signals:
    15. void generated(const QString &);
    16. private:
    17. int cnt;
    18. };
    19.  
    20. int main(int argc, char **argv){
    21. QApplication app(argc, argv);
    22. Dummy obj;
    23. app.connect(&obj, SIGNAL(generated(const QString &)), &te, SLOT(append(const QString &)));
    24. obj.start();
    25. return app.exec();
    26. }
    To copy to clipboard, switch view to plain text mode 

    In which case do you suggest using threads (except for network stuff of course), in which case do you suggest to avoid using threads ?
    Why except network stuff? You can do network stuff with Qt without or with using threads.

    In general threads should be used when the amount of work to do is heavy, can't be split into chunks (if it can, you can use the timer approach), you need many workers, it's not important that the task is executed immediately or in situations when it's simply very convenient to use threads.

    DISCLAIMER: The code above was not tested, don't assume it to work

  5. #5
    Join Date
    Apr 2006
    Posts
    29
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: QGraphicsScene and QThread

    Quote Originally Posted by wysota View Post
    In general threads should be used when the amount of work to do is heavy, can't be split into chunks (if it can, you can use the timer approach), you need many workers, it's not important that the task is executed immediately or in situations when it's simply very convenient to use threads.
    I completely agree with your example. This piece of code is a blocking task, but it is a "finite" task.

    Let's go back to our kinds of so-called "deamons". They are functionalities that can be run, suspended, re run again or completely stopped. Of course this handling of the task can also (and is in some sense), achieved by using signals (maybe using something like "disconnect", if it exists) but the main point is that we cannot know how long it will exist, it is an infinite task.

    So here is my first question: Does not using QTimers for such purposes induces avoidable computations ?

    And my second question: Does emitting signals to GUI widgets (that are not reentrant) from a thread completely avoids crashes due to the access of widgets data from a thread ?

    Is so I might reconsider my threads ;-)

    Thanks for your precisions!

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

    Default Re: QGraphicsScene and QThread

    Quote Originally Posted by jwintz View Post
    Of course this handling of the task can also (and is in some sense), achieved by using signals (maybe using something like "disconnect", if it exists) but the main point is that we cannot know how long it will exist, it is an infinite task.
    That doesn't matter. You can even use QObject::timerEvent() to avoid using an external timer, start the internal object timer and let it tick.

    So here is my first question: Does not using QTimers for such purposes induces avoidable computations ?
    It probably depends what you want to do and how your "daemons" are to work. For example if they are to work in an irregular way - they access a database using a blocking call, they access the disk very much, they wait until something else happens - then it is better to use threads for that. But if they just do the things in a regular way (for example update a clock widget, draw a chart, etc.), then you can do it with timers. Also note the fact, that using the timer approach with too many timers will slow down the application as all the actions will be executed when the time comes. With threads they can be deferred a little (until a context switch), making your application more responsive (nothing steals the CPU from the GUI).

    And my second question: Does emitting signals to GUI widgets (that are not reentrant) from a thread completely avoids crashes due to the access of widgets data from a thread ?
    Yes, signals are thread-safe in Qt4 as they'll use a thing called queued connections - consult the docs for details.

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.