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

Posted

技术标签:

【中文标题】如何在不同的 QT 线程中创建一个窗口?【英文标题】:How do I create a Window in different QT threads? 【发布时间】:2012-04-04 09:29:14 【问题描述】:

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

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

【问题讨论】:

不要尝试从后台/工作线程显示 UI。而是从主 GUI 线程显示该 UI。安排您的后台/工作人员向 GUI 线程发出信号以完成此操作。这个例子展示了如何做到这一点:doc.qt.nokia.com/4.7-snapshot/…. 【参考方案1】:

如果您需要在不同的(非主)线程中创建 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 ) );
..

要开心,:)

【讨论】:

你好,我做了一些小的改进只是为了好玩模板 class gui_launcher : public QObject mygui *w; // 其他组件 public: void add2Gui() this->moveToThread( QApplication::instance()->thread() ); QCoreApplication::postEvent(this, new QEvent(QEvent::User)); 虚拟布尔事件(QEvent *ev) if(ev->type() == QEvent::User) w = new mygui; w->显示();返回真; 返回假; ;【参考方案2】:

Qt 只允许您在 GUI 线程中创建 GUI 元素 - 您需要从其他线程中显示什么?有关使用来自非 GUI 线程的数据更新进度条的示例,请参见 This answer 之类的内容。

更新:

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

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 函数在哪里执行您需要它执行的操作。

【讨论】:

抱歉等待,我正在测试你的答案。 这是从 QThread 调用 QMessageBox 的完整示例。它与您的示例非常相似。 ***.com/a/23992291/999943【参考方案3】:

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

【讨论】:

【参考方案4】:

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

【讨论】:

以上是关于如何在不同的 QT 线程中创建一个窗口?的主要内容,如果未能解决你的问题,请参考以下文章

如何在我的 Qt 窗口中创建一个“洞”?

如何在 Qt 中创建 3D 对象模型的 2D 切片?

如何在 QT 中创建比主线程高优先级的线程

在 QDialog 中创建线程并在 Qt 中向 QDialog 发出信号

在 qt 中创建一个带有图像形状的窗口

如何在 PyQT5 中创建导航栏