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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9777911/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:16:40  来源:igfitidea点击:

How do I create a Window in different QT threads?

c++multithreadingqtuser-interface

提问by chacham15

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 runfunction. However, I get an error before I even get to that call: ASSERT failure in QWidget: "Widgets must be created in the GUI thread."

我有一个应用程序,其中每个线程(主线程除外)都需要创建自己的窗口。我尝试创建一个线程,然后调用this->exec()run函数。但是,在我接到那个电话之前,我收到了一个错误: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.

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

回答by aleksey_m_t

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:

如果您需要在不同的(非主)线程中创建 QWidget(或其他一些 gui 组件),您可以通过以下方式实现它:

  • 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, :)

  • 创建包含 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 ) );
    ..
    
  • 要开心, :)

回答by spbots

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 answerfor an example of updating a progress bar with data from a non-GUI thread.

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

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:

然后通过信号槽机制将其连接到您的 GUI,例如:

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

Where the showMessageBoxfunction does what you need it to do.

showMessageBox函数在哪里执行您需要它执行的操作。

回答by Tom Kerr

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.

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

回答by Massood Khaari

The above answers can be combined with a QActionobject (or custom class objects) to transfer any action to the main GUI thread to be executed, not just creating widgets or displaying a message box. (e.g. by emitting sendAction(QAction*), or implementing a custom QEventclass embodying a QAction*.)

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