PDA

View Full Version : [Newbie]: Suspending the main GUI thread



abhinavc
16th May 2010, 19:13
Hi all,
I am consistently getting stumped trying to do something (in PyQt4). And what I am looking for is some insight into what I could be doing wrong and ideas for what I should try next. I am pretty sure my problems are arising because of my imperfect understanding of QThread, QMutex and QWaitCondition.

What I have is a 3-stage GUI operation that goes from stage A to stage B and then finally to stage C. If no problems are detected in any of the stages, then the whole process should go from A -> C without human intervention. However, if a problem is detected in any stage, then my code throws an exception. At which point, I would like to show some sort of a feedback form (a QForm) explaining what the problem is with options for the user on how to proceed. Once the user selects an option, the process resumes.

When I first tried achieving the above, I noticed that while I could show the QForm, I could not stop the code in the main thread from going onto the next stage. Which is not right because the process should wait for the user's input. I figured that this is because all execution is happening only in one thread.

Then I tried using a QDialog. That helped (QDialog::exec() blocked main thread execution). But I want the feedback form to initially slide in from the right and slide back out once the user has made his selection. I could not achieve this effect with QDialog. Moreover, I don't want the form to have minimize, maximize and close buttons - which QDialog does. If the buttons are there, then the user might click on them and that would screw my operation's logic.

So, I tried doing the following when I first detect an error (and catch an exception):
1. create the QForm object in the main thread (because all GUI objects can only be created in the main thread)
2. Create a new class derived from QThread (let's call it BlockingThread)
3. Redfined run() for BlockingThread to call QThread::exec(). This should suspend the main thread (?)
4. Any QTimers I need to realize the sliding effect should be created and started in BlockingThread (?)
5. All code for the sliding effect should also be part of BlockingThread (?)

But the above also does not work. In fact, I get error messages like the ones below:

QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x8809520), parent's thread is QThread(0x84b66f0), current thread is BlockingThread(0x8838870)

So now I don't know how to proceed or what new idea to try. Hence, if you have any insight or past experience with the implmenting something similar, then please let me know.

Thanks in advance for your help
Abhinav,

squidge
16th May 2010, 20:13
Seems that what you want is to create a form with a specific modality. The sliding is done in the new forms event loop, and the main form will not continue execution until it has been signalled by the new form that it has been closed. This also means that the main forms event loop isn't stopped.

wysota
16th May 2010, 20:50
To complement what was already said - you don't need any extra threads, one thread is enough.

abhinavc
16th May 2010, 22:41
Seems that what you want is to create a form with a specific modality. The sliding is done in the new forms event loop, and the main form will not continue execution until it has been signalled by the new form that it has been closed. This also means that the main forms event loop isn't stopped.

Thanks a ton... I started to create an example after I posted to mimic what I wanted. And after your response, I decided
to create QEventLoop objects in my QFrame (not QForm) classes. Works on the small example. Now I have to try it on the
big one.

That said, I can't say my Qt-intuition is quite developed yet. For one, I don't understand how this magical thing called
QEventLoop is implemented. Perhaps it will hit me suddenly one day. It certainly wouldn't now at 2:11am.