2012-03-19 24 views
10

Tengo una aplicación en la que cada hilo (excepto el hilo principal) necesita crear su propia ventana. Intenté crear un hilo y luego llamar al this->exec() en la función run. Sin embargo, me aparece un error antes de llegar a esa llamada: ASSERT failure in QWidget: "Widgets must be created in the GUI thread."¿Cómo creo una ventana en diferentes subprocesos de QT?

Quiero abrir una ventana de mensaje. El problema es que la fuente tiene múltiples hilos, cada uno de los cuales puede necesitar mostrar su propio mensaje.

+2

No intente mostrar UI desde los hilos de fondo/trabajo. En cambio, muestra esa interfaz de usuario desde el hilo principal de la GUI. Haga arreglos para que su fondo/trabajador señale el hilo de la GUI para poder hacer esto. Este ejemplo muestra cómo hacerlo: http://doc.qt.nokia.com/4.7-snapshot/thread-basics.html#example-3-clock. –

Respuesta

19

Si necesita crear QWidget (o algún otro componente (s) GUI) en diferente (no principal) hilo (s) se puede aplicar en tal manera:

  • Crear envoltorio sencillo que sostiene el componente de interfaz gráfica de usuario:

    // 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; 
        } 
    }; 
    
  • crear el objeto QApplication en hilo principal

  • otro cuerpo hilo:

    .. 
        // 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)); 
    .. 
    
  • ser feliz, :)

+2

Hola Hice alguna pequeña mejora sólo por diversión \t plantilla clase gui_launcher: QObject pública { mygui * w; // otros componentes pública: \t add2Gui void() { \t \t \t \t this-> moveToThread (QApplication :: ejemplo() -> hilo()); \t \t QCoreApplication :: postEvent (esto, nuevo QEvent (QEvent :: User)); \t \t} evento bool virtual (QEvent * ev) { si (EV> TIPO() == QEvent :: Usuario) { w = new mygui; w-> show(); return true; } return false; } }; – jamk

1

No creo que esto es posible. Otros componentes que no son GUI pueden ejecutarse en otros hilos y normalmente se comunicarán a través de los mecanismos de señal/ranura.

7

Qt solo le permitirá crear elementos de la GUI en el hilo de la GUI, ¿qué es lo que necesita mostrar de los otros hilos? Vea algo como This answer para ver un ejemplo de actualización de una barra de progreso con datos de un hilo que no es GUI.

Actualización:

Si desea mostrar un mensaje para cada ventana, se puede tener una clase como esta:

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

A continuación, conectarlo a su interfaz gráfica de usuario a través de la señal de la ranura mecanismo con algo como:

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

Cuando la función showMessageBox hace lo que necesita hacer.

+0

actualizada pregunta – chacham15

+0

respuesta actualizado con un pequeño ejemplo :) – spbots

+0

sry por la espera, que estaba probando su respuesta a cabo. – chacham15

0

Las respuestas anteriores pueden combinarse con un (objetos o clases personalizadas) QAction objeto de transferir cualquier acción que el hilo principal interfaz gráfica de usuario para ser ejecutado, no sólo crear widgets o mostrar un cuadro de mensaje. (por ejemplo, emitiendo sendAction(QAction*), o implementando una clase personalizada QEvent que incorpora un QAction*.)

Cuestiones relacionadas