如何在不同的QT线程中创建窗口

How do I create a Window in different QT threads?

本文关键字:线程 创建 窗口 QT      更新时间:2023-10-16

我有一个应用程序,其中每个线程(主线程除外)都需要创建自己的窗口。我尝试创建一个线程,然后在run函数中调用this->exec()。然而,我在接到那个电话之前就收到了一个错误:ASSERT failure in QWidget: "Widgets must be created in the GUI thread."

我想弹出一个消息窗口。问题是源有多个线程,每个线程可能需要弹出自己的消息。

如果你需要在不同的(非主)线程中创建QWidget(或其他一些gui组件),你可以这样实现:

  • 创建一个包含gui组件的简单包装器:

    // 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;
      }
    };
    
  • 在主线程中创建QApplication对象

  • 另一个线程体:

    ..
      // 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 ) );
    ..
    
  • 要高兴,:)

Qt只允许您在GUI线程中创建GUI元素-您需要从其他线程显示什么?有关使用非GUI线程中的数据更新进度条的示例,请参阅类似"此答案"的内容。

更新:

如果你想为每个窗口显示一条消息,你可以有一个这样的类:

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 */
  }
};

然后通过信号槽机制将其连接到您的GUI,类似于:

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

其中showMessageBox函数执行您需要它执行的操作。

我认为这是不可能的。其他非GUI组件可以在其他线程中运行,并且通常通过信号/插槽机制进行通信。

以上答案可以与QAction对象(或自定义类对象)组合,将任何操作转移到要执行的主GUI线程,而不仅仅是创建小部件或显示消息框。(例如,通过发射sendAction(QAction*),或实现包含QAction*的自定义QEvent类。)