Hi,
is there a way to show a QMessageBox and get the return code (yes/no message box) out of a thread (QThread subclass)?
Thanks!
Chris
Printable View
Hi,
is there a way to show a QMessageBox and get the return code (yes/no message box) out of a thread (QThread subclass)?
Thanks!
Chris
Unfortunately no, because you may not touch the GUI from any other than the main GUI thread.
...mmmhhhh, no chance with connections or events?
If the messagebox create process in main thread and call this with connection from second thread and return the result (yes/no) back via connection to second thread?
Of course it's possible. The messagebox just has to be exec'd in the main thread. Use queued signals or custom events to deliver the information between threads.
Ok, but the second thread must be wait for messagebox reply! How?
Well, it depends pretty much how the thread is running. Is it running an event loop or is everything done in QThread::run()? You could start with taking a look at the thread examples shipped with Qt.
It's not implemented yet! I think, in QThread:run()! Is the event loop better?
IMO eventually you'll have to use a wait condition to put the waiting thread to sleep. And the message box would have to be shown using show() and not exec(), otherwise it'll block the main thread execution which makes all the situation with using another thread highly doubtfull.
To me it smells a little like a bad design somewhere...
Just curious, what is the thread actually processing?
Nothing, it's not implemented yet! It's a consideration so far!
I have an application that uses tape drives. The thread needs to ask if there are any more tapes for the job, SCSI errors, file dialogs...
This method uses QT3, I have not ported this application to QT4 yet.
Code:
in your application void TapeMan::customEvent( QCustomEvent *event ) { { MessageBoxEvent *me = ( MessageBoxEvent* )event; ThreadMessageBox *tm = me->tm; if( me->kind == TMSG_WARN ) me->button0, me->button1, me->button2 ); if( me->kind == TMSG_INFO ) me->message, me->button0, me->button1, me->button2 ); if( me->kind == TMSG_STOP ) me->button0, me->button1, me->button2 ); } } and then 2 classes #ifndef THREADMESSAGEBOX_H #define THREADMESSAGEBOX_H #include <qstring.h> #include <qmessagebox.h> class ThreadMessageBox { public: ~ThreadMessageBox(); int messageResult; }; #endif #include "threadmessagebox.h" #include "messageboxevent.h" #include <qapplication.h> extern TapeMan *gApp; const QString& message, int button0, int button1, int button2 ) { MessageBoxEvent *mess = new MessageBoxEvent( this, kind, caption, message, button0, button1, button2 ); messageResult = -99999; while( messageResult == -99999 ) // wait { sleep( 1 ); } } ThreadMessageBox::~ThreadMessageBox() { } #ifndef MESSAGE_BOX_EVENT_H #define MESSAGE_BOX_EVENT_H #include <qevent.h> #include <qmessagebox.h> #include <qdeepcopy.h> class ThreadMessageBox; class MessageBoxEvent : public QCustomEvent { public: ~MessageBoxEvent(); THREAD_MESSAGE kind; // kind of message box QDeepCopy<QString> caption; // caption for message box QDeepCopy<QString> message; // text for message int button0; // buttons to display int button1; int button2; ThreadMessageBox *tm; // pointer to thread message box }; #endif #include "messageboxevent.h" MessageBoxEvent::MessageBoxEvent( ThreadMessageBox *tm, THREAD_MESSAGE kind, { this->kind = kind; this->caption = caption; this->message = message; this->button0 = button0; this->button1 = button1; this->button2 = button2; this->tm = tm; } MessageBoxEvent::~MessageBoxEvent() { } to get a message box from your thread ThreadMessageBox mess = ThreadMessageBox( TMSG_INFO, "Tape Done", "Are there any more tapes", // do action here!
You need to use QDeepCopy's to insure each thread has a unique copy of the strings. This is not needed in QT4. The wait loop is a simple sleep. That is all that was needed for this application.
As long as the tQThread object was created in the Gui thread, you can set up a connection between a private signal and a private slot. For the synchronization you need a QWaitCondition and a QMutex.
e.g.:
Code:
{ Q_OBJECT public: protected: virtual void run(); signals: private slots: private: QWaitCondition waitCondition; QMutex mutex; }; { } void WorkingThread::run() { do { emit askAQuestion( "do you want to continue?", &answer); waitCondition.wait(&mutex); } } { waitCondition.wakeOne(); }
The connection will automatically be queued since the run() function doesn't reside in the same thread as the QThread object, thus it's safe to use a messagebox.
Good luck!