2010-05-09 6 views
10

Ich muss eine QApplication in einem Thread ausführen, der nicht Haupt ist (meine GUIs müssen Plugins sein, die zur Laufzeit dynamisch geladen und entladen werden können, also habe ich keinen Zugriff auf den Haupt-Thread) . Kennt jemand einen (relativ) schmerzlosen Weg, Qt's Beschränkung gegen das Starten von QApplication außerhalb von Main zu hacken?QApplication in Nicht-Haupt-Thread

Ich entwickle in Linux mit Qt4 in C++ mit gcc4.3.4.

Antwort

4

Wenn Sie QThread verwenden, dann haben Sie bereits normale Qt Event-Schleife und kann nur exec() in QThread :: run() -Funktion ausführen. Während Sie nicht mit GUI-Objekten außerhalb des Hauptthreads arbeiten können, können Sie dennoch mit ihnen über eingereihte Signal/Slot-Verbindungen interagieren. Vielleicht können Sie versuchen, den Zeiger auf das QThread-Objekt des Hauptthreads zu speichern und QObject :: moveToThread() aufzurufen, um Ihre GUI-Objekte in den Hauptthread zu verschieben, anstatt QApplication in einen anderen Thread zu verschieben.

Ich denke, es ist nicht wirklich eine gute Idee zu versuchen, gegen Toolkit mit verschiedenen Arten von Hacks und Kluges zu gehen.

+0

Ich denke, Sie können Recht haben, VestniK - Während meine GUI tatsächlich ausgeführt wird, scheint es nicht update() -Aufrufe zu bedienen, außer ich zwinge das OS, die GUI neu zu zeichnen, indem ich ein anderes Fenster darüber ziehe. – rcv

+0

Ich fand diese Antwort nützlich, um ein anderes Problem zu lösen, aber während ich das QMainWindow-Objekt von einem anderen Thread in den Haupt-Thread verlagerte, erhielt ich 'QObject :: moveToThread: Widgets können nicht in einen neuen Thread verschoben werden – ASten

1

Patch Qt, ich denke und entfernen Sie die Überprüfung der Hauptthread, und testen Sie, ob das für Sie funktioniert. Nach http://bugreports.qt-project.org/browse/QTBUG-7393 , die nicht unter OS X/Cocoa funktionieren, da Cocoa davon ausgeht, dass der erste Thread der Haupt/UI-Thread ist.

1

Ok, ich habe etwas, das funktioniert! Es ist nicht schön, aber es macht definitiv seinen Job.

  1. erstellen QMainWindow Derivat mit all Ihren aktuellen Code GUI in sie und überlasten das Ereignis() Funktion dieser Klasse this- nennen> show()

  2. Erstellen Sie eine Klasse (nennen wir es Runner), die einen Zeiger auf Ihr QMainWindow-Derivat halten und ihm eine Lauffunktion geben wird.

  3. Im Runner :: Runner(), einen Thread starten die Läufer nennen :: run()

  4. In Runner :: run() (die jetzt in einem eigenen Thread ausgeführt wird) konstruieren eine QApplication und eine Instanziierung Ihres QMainWindow-Derivats. Rufen Sie die Funktion exec() der QApplication auf.

  5. Jetzt, wenn Sie Ihre GUI starten möchten, buchen Sie einfach jedes Ereignis auf Ihrem QMainWindow-Derivat, und es wird sich zeigen!

Diese Lösung scheint in Linux sehr gut zu funktionieren, obwohl es scheint wirklich etwas Lücke in Qt zu nutzen und kann auf anderen Plattformen nicht funktionieren. Definitiv einfacher als Qt zu patchen.

+0

Hey Boatzart, ich versuche das Gleiche zu erreichen. Wenn du "the Runner :: Runner()" sagst, starte einen Thread, der Runner :: run() aufruft ", was meinst du?Starten Sie einen anderen QThread, der Runner-Thread starten würde? Aber wie könnten Sie einen anderen Thread starten, ohne QApplication zu erstellen? – blueskin

8

Sie können eine QApplication in einem Pthread beginnen, wie unten

//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); 
} 
Verwandte Themen