2009-07-17 3 views
9

Soy nuevo en QT y estoy aprendiendo algo.QT + Cómo llamar a la ranura desde el código personalizado de C++ que se ejecuta en una secuencia diferente

Me gustaría activar una ranura que modifique un widget GUI a partir de un hilo C++ (actualmente un Qthread).

Desafortunadamente consigo una: Error de aserción en: Q_ASSERT (QAPP & & qApp-> hilo() == QThread :: currentThread());

Aquí hay un código:

(clase hilo principal +)

class mythread : public QThread 
    { 
    public: 
     mythread(mywindow* win){this->w = win;}; 
     mywindow* w; 
     void run() 
     { 
      w->ui.textEdit->append("Hello");  //<--ASSERT FAIL 
      //I have also try to call a slots within mywindow which also fail. 
     }; 
    }; 

    int main(int argc, char *argv[]) 
    { 
     QApplication* a = new QApplication(argc, argv); 
     mywindow* w = new mywindow(); 

     w->show(); 
     mythread* thr = new mythread(w); 
     thr->start(); 

     return a->exec(); 
    } 

Ventana:

class mywindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    mywindow (QWidget *parent = 0, Qt::WFlags flags = 0); 
    ~mywindow(); 
    Ui::mywindow ui; 

private: 



public slots: 
    void newLog(QString &log); 
}; 

Así que tengo curiosidad sobre cómo actualizar la parte GUI de código en una hilo diferente.

Gracias por ayudar

Respuesta

6

Además de stribika's answer, a menudo resulta más fácil de usar una conexión de señal/ranura. Puede especificar que debe ser una conexión en cola cuando la conecta, para evitar problemas con las señales del hilo en el contexto de su objeto propietario.

class mythread : public QThread 
{ 
signals: 
    void appendText(QString); 
public: 

    mythread(mywindow* win){this->w = win;}; 
    mywindow* w; 
    void run() 
    { 
     emit (appendText("Hello")); 
    }; 
}; 

int main(int argc, char *argv[]) 
{ 
    QApplication* a = new QApplication(argc, argv); 
    mywindow* w = new mywindow(); 

    w->show(); 
    mythread* thr = new mythread(w); 
    (void)connect(thr, SIGNAL(appendText(QString)), 
        w->ui.textEdit, SLOT(append(QString)), 
        Qt::QueuedConnection); // <-- This option is important! 
    thr->start(); 

    return a->exec(); 
} 
+3

La clase mythread necesita contener la macro Q_OBJECT – CiscoIPPhone

4

Es necesario utilizar QMetaObject::invokeMethod. Por ejemplo:

void MyThread::run() { 
    QMetaObject::invokeMethod(label, SLOT(setText(const QString &)), Q_ARG(QString, "Hello")); 
} 

(El código anterior proviene de aquí: http://www.qtforum.org/article/26801/qt4-threads-and-widgets.html)

+0

... y está mal :) –

+0

@ MarcMutz-mmutz ¿podría explicar también qué está mal con este código? Sospecho que es la macro SLOT, pero podría ser que tuvieras otro punto ;-) – FourtyTwo

+0

'invokeMethod' solo toma el nombre de la función (' '" setText "' '), no el resultado de' SLOT'. –

2

no creo que se les permite llamar directamente a las cosas que se traduce en eventos de pintura de cualquier otro hilos que el hilo principal. Eso dará lugar a un bloqueo.

Creo que puede usar el bucle de eventos para llamar a las cosas de forma asincrónica, de modo que el hilo de la interfaz principal se recupere y luego realice la actualización desde el hilo principal, que es lo que sugiere cjhuitt.

11

stribika consiguieron casi a la derecha: la derecha

QMetaObject::invokeMethod(textEdit, "append", Qt::QueuedConnection, 
          Q_ARG(QString, myString)); 

de cjhuitt, sin embargo: Por lo general, desea declarar una señal en la rosca y conectarlo a la ranura append(), para conseguir la gestión de objetos de por vida gratis (bueno, por el precio de un cambio de interfaz menor). En una nota, el argumento adicional:

   Qt::QueuedConnection); // <-- This option is important! 

de la respuesta de cjhuitt ya no es necesario (que era, en Qt < = 4,1), ya que connect() defecto Qt::AutoConnection que ahora (Qt> = 4.2) hace la derecha y cambia entre el modo de conexión en cola y directo basado en QThread::currentThread() y la afinidad de subprocesos del receptor QObject en emiten hora (en lugar de afinidad entre el emisor y el receptor en el momento de la conexión).

+2

No sabía que la conexión estaba ahora en la hora de emisión ... ¿esto todavía funciona con objetos de hilo, que "viven" en la secuencia donde se creó, no el hilo que se genera cuando se llama QThread :: run? (Acabamos de tener un debate sobre esto hace un par de semanas en el trabajo, y decidimos que era más seguro especificar la opción QueuedConnection en esos casos). –

+1

Lo he usado para emitir señales de Threads que no son Qthreads en absoluto . Funciona muy bien para enviar eventos al bucle principal de Qt. Además, nunca tuvo que especificar QueuedConnection con Qt 4.3 y superior. – Macke

1

¿Qué pasa si nuestra afinidad por el hilo dice GUI, pero no estamos en el hilo de GUI, ni en un QThread?

Lo que quiero decir es que un subproceso no de Qt (notificación) llama al método de interfaz de QObject, en el que se emite una señal de Autoconexión.La afinidad de Subproceso del QObject es el subproceso Principal, pero el procedimiento se llama realmente desde otro subproceso. ¿Qué hará el Qt aquí?

Cuestiones relacionadas