Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a Window in different QT threads?

I have an application in which each thread (except the main thread) needs to create its own window. I tried creating a thread and then calling this->exec() in the run function. However, I get an error before I even get to that call: ASSERT failure in QWidget: "Widgets must be created in the GUI thread."

I want to popup a message window. The problem is that the source has multiple threads each of which may need to popup its own message.

like image 952
chacham15 Avatar asked Mar 19 '12 21:03

chacham15


People also ask

How do I create a window in Qt?

Let's open up Designer by double-clicking the mainwindow. ui to put menu bar and action. Type in "File" at the top menu, and "New Window..." under the "File" menu. We need to press Enter to make a real change in the menu.

What is thread in Qt?

A QThread object manages one thread of control within the program. QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread. You can use worker objects by moving them to the thread using QObject::moveToThread().


3 Answers

If you need to create QWidget(or some other gui component(s)) in different(non-main) thread(s) you can implement it in such way:

  • Create simple wrapper which holds gui component:

    // gui component holder which will be moved to main thread
    class gui_launcher : public QObject
    {
      QWidget *w;
      // other components
      //..
    public:
      virtual bool event( QEvent *ev )
      {   
        if( ev->type() == QEvent::User )
        {
          w = new QWidget;
          w->show();
          return true;
        }
        return false;
      }
    };
    
  • create QApplication object in main thread

  • another thread body:

    ..
      // create holder
      gui_launcher gl;
      // move it to main thread
      gl.moveToThread( QApplication::instance()->thread() );
      // send it event which will be posted from main thread
      QCoreApplication::postEvent( &gl, new QEvent( QEvent::User ) );
    ..
    
  • be happy, :)

like image 159
aleksey_m_t Avatar answered Oct 18 '22 17:10

aleksey_m_t


Qt will only let you create GUI elements in the GUI thread - what is it that you need to display from the other threads? See something like This answer for an example of updating a progress bar with data from a non-GUI thread.

Update:

If you want to show a message for each window, you can have a class like this:

class MyWorkerThread : public QThread
{
  Q_OBJECT
signals:
  void sendMessage(QString msg);
private:
  void run()
  {
    /* do stuff */
    emit sendMessage(QString("This thread is doing stuff!"));
    /* do more stuff */
  }
};

Then connect it up to your GUI via the signal-slot mechanism with something like:

connect(workerThread, SIGNAL(sendMessage(QString)),
        guiController, SLOT(showMessageBox(QString)));

Where the showMessageBox function does what you need it to do.

like image 43
spbots Avatar answered Oct 18 '22 18:10

spbots


I don't believe this is possible. Other non-GUI components can run in other threads and will usually communicate via the signal/slot mechanisms.

like image 36
Tom Kerr Avatar answered Oct 18 '22 17:10

Tom Kerr