PDA

View Full Version : QMessageBox in a second thread?



realdarkman71
22nd May 2011, 22:22
Hi all,

I have a second thread outside the main (GUI) thread, this (second) thread copys a directory with all subdirs and all files. If a file is exists, I have a (modal) QMessageBox for asking the user to override or not. But it comes:


QObject::setParent: Cannot set parent, new parent is in a different thread
QPixmap: It is not safe to use pixmaps outside the GUI thread

How can I do this?

Thx!
Chris

wysota
22nd May 2011, 22:28
You can't use widgets in worker threads. Communicate with the main thread (e.g. using signals) and show the message box from there.

realdarkman71
22nd May 2011, 22:36
Ok, but after emits the signal, the copy routines continues! It's must wait for users choise (override or not)!

squidge
22nd May 2011, 23:05
Then you need to wait for the response from the gui thread before you continue. You probably have a list of files to work through, so just keep the index and resume from where you left off when you get the appropriate signal from the main thread.

wysota
23rd May 2011, 00:29
Or use the signal semantics that will halt the execution of the worker thread until all the slots are executed.

realdarkman71
23rd May 2011, 11:15
This works, thanks! ...but the return value is always the same!?

Slot in GUI thread:

int overrideQuestion(const QString fileName) {
return QMessageBox::question(this, tr("Override?"), tr("File '%1' already exists! Override?").arg(fileName), QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll);
}

In copy thread:



signals:
int overrideQuestion(const QString);

(...)

connect(this, SIGNAL(overrideQuestion(QString)), parent, SLOT(overrideQuestion(QString)), Qt::BlockingQueuedConnection);

(...)

int result = emit overrideQuestion(fileInfo.fileName());


result is always "267386880"!?

wysota
23rd May 2011, 15:37
Return values from slots are ignored.

realdarkman71
23rd May 2011, 16:23
Ok, but how can I do this with an int return value?

wysota
23rd May 2011, 16:34
You can use a shared variable, for example.

realdarkman71
23rd May 2011, 16:36
Sorry, I don't understand it! :confused: Variable as return value???

squidge
23rd May 2011, 17:26
The slot will not return anything. You either need to store the variable elsewhere or you need to send a signal to the thread to indicate the return value. I would use a state machine in the thread and use a signal to indicate the return value (ie, the thread would change to paused state when the notification is raised and resume upon receiving the response from the user).

You might have guessed that I hate blocking code, so everything runs via events and signals :)

I've written a file manager before that goes one step further - if it needs a response from the user (eg. overwrite question), it sends a signal to the main thread to request about that file and processes the other files in the background, returning to the other files if and when a response is received from the main thread about those files.

realdarkman71
23rd May 2011, 17:59
store variable elsewhere .. can you give me an example with my above code please!?

squidge
23rd May 2011, 19:25
eg. you store the result from the message dialog in a variable that both threads have access it. I don't think you really need an example for that.

But I would say that the method I described above is a better idea and keeps encapsulation.

realdarkman71
23rd May 2011, 21:56
Ok, but how can I paused the worker thread?

squidge
23rd May 2011, 23:03
You don't "pause" it, you simply return to your threads event loop waiting for something to happen (such as a signal from the main ui to continue). When you receive this signal, you continue, using the context information you stored in your thread when you returned to the event loop.

I assume you store your filenames in a vector or similar, so all you need to do is store an iterator to the element you were parsing when you emitted the message box request, then you restart from there once you receive the information back from the main thread.

realdarkman71
23rd May 2011, 23:32
Ok, thanks to all for your help!