Как мне создать окно в разных потоках QT? - PullRequest
15 голосов
/ 20 марта 2012

У меня есть приложение, в котором каждый поток (кроме основного потока) должен создать свое собственное окно. Я попытался создать поток и затем вызвать this->exec() в функции run. Тем не менее, я получаю сообщение об ошибке еще до того, как доберусь до этого вызова: ASSERT failure in QWidget: "Widgets must be created in the GUI thread."

Я хочу открыть окно сообщения. Проблема в том, что в источнике есть несколько потоков, каждый из которых может нуждаться во всплывающем сообщении.

Ответы [ 4 ]

21 голосов
/ 15 октября 2012

Если вам нужно создать QWidget (или какой-либо другой компонент (ы) графического интерфейса) в другом (неосновном) потоке (ах), вы можете реализовать его следующим образом:

  • Создать простую оболочку, которая содержит компонент графического интерфейса:

    // 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 ) );
    ..
    
  • будь счастлив, :)

7 голосов
/ 20 марта 2012

Qt позволит вам только создавать элементы 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 */
  }
};

Затем подключите его к графическому интерфейсу через механизм сигнальных слотов с чем-то вроде:

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

Где функция showMessageBox делает то, что вам нужно.

1 голос
/ 20 марта 2012

Я не верю, что это возможно. Другие компоненты, не относящиеся к графическому интерфейсу, могут работать в других потоках и обычно обмениваются данными через механизмы сигнала / слота.

0 голосов
/ 10 марта 2013

Приведенные выше ответы можно комбинировать с объектом QAction (или объектами пользовательского класса) для передачи любого выполняемого действия в основной поток графического интерфейса пользователя, а не просто создания виджетов или отображения окна сообщения. (например, путем выдачи sendAction(QAction*) или реализации пользовательского QEvent класса, включающего QAction*.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...