2010-05-09 18 views
10

Ho bisogno di exec() a QApplicazione in un thread che non è main (le mie GUI devono essere plugin che possono essere caricati e scaricati dinamicamente in fase di runtime, quindi non ho accesso al thread principale) . Qualcuno sa di un modo (relativamente) indolore per aggirare la restrizione di Qt contro l'avvio di QApplication al di fuori del main?QApplicazione in thread non principale

Sto sviluppando in Linux con Qt4 in C++ utilizzando gcc4.3.4.

risposta

4

Se si utilizza QThread, si ha già un ciclo di eventi Qt normale e si può semplicemente eseguire exec() all'interno della funzione QThread :: run(). Sebbene non sia possibile lavorare con oggetti GUI al di fuori del thread principale, è comunque possibile interagire con essi tramite connessioni segnale/slot in coda. Forse puoi provare a memorizzare il puntatore sull'oggetto QThread del thread principale e chiamare QObject :: moveToThread() per spostare gli oggetti della GUI nel thread principale invece di spostare QApplication in un altro thread.

Penso che non sia una buona idea cercare di andare contro il toolkit con diversi tipi di hack e kluges.

+0

Penso che potresti avere ragione, VestniK - Anche se la mia GUI è effettivamente in esecuzione, sembra che non funzioni effettivamente le chiamate di update() a meno che non costringa il sistema operativo a ridisegnare la GUI trascinandone un'altra finestra sopra. – rcv

+0

Ho trovato questa risposta utile per risolvere un altro problema, ma durante lo spostamento dell'oggetto QMainWindow da un altro thread a quello principale ho ricevuto 'QObject :: moveToThread: I widget non possono essere spostati in un nuovo thread' – ASten

1

Patch Qt, credo e rimuovo il controllo del thread principale e verifica se questo funziona per voi. Secondo http://bugreports.qt-project.org/browse/QTBUG-7393 che non funzionerà su OS X/Cocoa, poiché Cocoa presuppone che il primo thread generato sia il thread principale/dell'interfaccia utente.

1

Ok, ho qualcosa che funziona! Non è carino, ma sicuramente fa il lavoro.

  1. Creare un derivato QMainWindow con tutto il codice della GUI effettivo in esso e sovraccaricare la funzione di evento() di questa classe di chiamare this-> show()

  2. Creare una classe (chiamiamolo Runner) che manterrà un puntatore alla derivata QMainWindow e gli darà una funzione run.

  3. Nel Runner :: Runner(), avviare un filo che chiamerà Runner :: run()

  4. In Runner :: run() (che è ora in esecuzione in un suo filo) costruire una domanda Q e un'istanza della derivata QMainWindow. Chiama la funzione exec() di QApplication.

  5. Ora, quando si desidera avviare la GUI, basta postare qualsiasi evento alla derivata QMainWindow e si mostrerà!

Questa soluzione sembra funzionare molto bene in Linux, anche se sembra davvero di essere sfruttando qualche scappatoia in Qt e potrebbe non funzionare su altre piattaforme. Decisamente più facile che applicare le patch a Qt.

+0

Hey Boatzart, sto cercando di ottenere la stessa cosa. Quando dici "il Runner :: Runner(), avvia una discussione che chiamerà Runner :: run()", cosa intendi.Avvia un altro QThread che avvia il thread Runner? Ma come è possibile iniziare un altro thread senza costruire QApplication? – blueskin

8

È possibile avviare una QApplication in un pthread, come di seguito

//main.cpp

#include <iostream> 
#include "appthread.h" 
int main(int argc, char *argv[]) { 
    InputArgs args = {argc, argv}; 
    StartAppThread(args); 
    sleep(10); 
    return 0; 
} 

//appthread.h

struct InputArgs{ 
    int argc; 
    char **argv; 
}; 
void StartAppThread(InputArgs &); 

//appthread.cpp

#include <QApplication> 
#include <QMainWindow> 
#include <QPushButton> 
#include "appthread.h" 
#include <pthread.h> 

void *StartQAppThread(void *threadArg) { 
    InputArgs *args = (struct InputArgs*) threadArg; 
    QApplication app(args->argc, args->argv); 
    QMainWindow w; 
    w.show(); 
    w.setCentralWidget(new QPushButton("NewButton")); 
    app.exec(); 
    pthread_exit(NULL); 
} 

void StartAppThread(InputArgs &args) { 
    pthread_t thread1; 
    int rc = pthread_create(&thread1, NULL, StartQAppThread, (void*)&args); 
} 
Problemi correlati