I would like to affect a QDialog from a separate thread, I have to do two things:
dialog->show();
dialog->raise();
dialog->activateWindow();
As far as I understand, these are events and thus MUST be done in the main thread event loop. I think I achieve this with QApplication::postEvent
within in the QThread::run()
. Could anyone confirm?
Second, I would like to display an image which was processed in that separate thread. I think I need to subclass my dialog class and write a thread safe setImage()
function, which is then called by paintEvent()
... However, this seems like it's impossible. I can't block the paintEvent with a QMutex::unlock()
? Could anyone offer some suggestions?
QApplication::postEvent(dialog, new QShowEvent());
did not work.
This is the solution for calling slots (as functions) from a seperate thread:
QMetaObject::invokeMethod(dialog, "show", Qt::QueuedConnection);
QMetaObject::invokeMethod(dialog, "raise", Qt::QueuedConnection);
... Still working on activateWindow()
and QThread
safe functions.
So for the QImage
, it is a QPaintDevice. Supposedly it is thread safe. My approach would've been to have a class member QImage
that is set within the thread. Then painted later.
Note, that the below approach is as good, if not better though.
I think this is a clearer way to do what you want:
class Dialog : public QDialog
{
...
public slots:
void showImage(QImage img);
...
}
void Dialog::showImage(QImage img);
{
setImage(img);
show();
raise();
activateWindow();
}
class Thread : public QThread
{
...
signals:
void imageReady(QImage);
}
void Thread::run()
{
QImage img;
/// image processing stuff
emit imageReady(img);
...
}
Thread *thread = new Thread;
Dialog *dialog = new Dialog;
connect(thread, SIGNAL(imageReady(QImage)), dialog, SLOT(showImage(QImage)));
thread->start();