2011-01-03 9 views
0

Ich habe den Hauptthread (GUI), der einen QThread erzeugt.Anzeige einer QMessageBox aus C-Code, der in einem QThread läuft

In der QThread, rufe ich eine C-Funktion, die eine QMessageBox anzeigen muss. Bisher habe ich einfach verwendet:

void notify(char *str) 
{ 
    QMessageBox::information(0, "", QString(str)); 
} 

im C++ - Code und rief es aus dem C-Code. Dies funktioniert ohne Threads, aber jetzt mit Threads bekomme ich Fehler, weil man die GUI-Funktionen nicht von einem anderen Thread aufrufen kann.

Normalerweise könnte dies umgangen werden mit Signalen wie die Antwort auf this question schlägt vor; Ich bezweifle jedoch, dass ich das vom C-Code aus tun kann.

Also, wie kann ich den C-Code mit dem GUI-Thread kommunizieren lassen und ihm mitteilen, dass er eine QMessageBox anzeigen soll?

Danke.

P.S.

Wenn möglich, würde ich dies tun, ohne den C-Code zu berühren (ab sofort gibt es einfach eine extern void notify(char *) Deklaration in den Kopfzeilen des C-Codes, und wenn möglich, möchte ich es bleiben.

Antwort

3

Sie haben eine QWidget oder QMainWindow abgeleitete Klasse für Ihre GUI Unter der Annahme, könnten Sie die folgenden, um es hinzuzufügen.

class MyWidget : public QWidget 
{ 
    Q_OBJECT; 
public:  
    MyWidget() 
    { 
     connect(this, SIGNAL(notify_sig(QString)), 
       this, SLOT(notify_slot(QString)), 
       Qt::QueuedConnection); 
    } 

    void notify(QString str) 
    { 
     emit notify_sig(str); 
    } 

    signals: 
     void notify_sig(QString str); 

    slots: 
     void notify_slot(QString str) 
     { 
      QMessageBox::information(0, "", str); 
     } 
}; 

Hier haben Sie eine öffentliche Funktion notify(), das ein Mitglied der Widget-Klasse aufrufen MyWidget::notify() Ergebnisse in einem Signal, das durch eine Warteschlangenverbindung an sich selbst gesendet wird (was dazu führt, dass der Slot im GUI-Thread aufgerufen wird). Jetzt muss der C notify() Aufruf nur die Funktion notify() des Widgets/Fensters aufrufen. Dies kann schwierig sein, da Sie keinen Zeiger auf das Widget in der C notify() Funktion haben.

Normalerweise würde die C-Schnittstelle dem Benutzer ermöglichen, einen void* Wert in übergeben und würde dann diesen Wert mit dem Notify-Aufruf zurückgeben. Dadurch können Sie den Zeiger auf MyWidget übergeben, wenn die C-Funktion aufgerufen wird, und dann in MyWidget in der notify() Implementierung zurückgeworfen werden.

MyWidget* wid = ...; 
C_function(arg1, ..., wid); 

//... 

void notify(char* str, void* userdata) 
{ 
    MyWidget* wid = static_cast<MyWidget*>(userdata); 
    wid->notify(QString(str)); 
} 

Wenn Sie die C-Schnittstelle ändern können, können Sie irgendeine Art von globaler Art und Weise des Erhaltens des Widgets/Fensters Zeiger verwenden müssen.

Beachten Sie, dass ich diesen Code nicht getestet habe und es möglicherweise einen einfacheren Weg gibt, dies zu tun.

+0

Vielen Dank für Ihre Antwort! Ich denke, du hast meine Antwort ein wenig falsch verstanden oder ich habe es falsch erklärt, aber die 'notify' (nicht-klassen) -Funktion ist eigentlich im C++ - Code (der C-Code nennt es nur), was es ein wenig einfacher macht, da ich es kann ** Holen Sie den Zeiger auf das 'MyWidget' in Ihrem Beispiel. Also kann ich die Methoden meiner Hauptfensterklasse aufrufen, die dann Signale und Slots verwenden, wie Sie es vorgeschlagen haben. Aber wie auch immer, ich habe Ihren Ansatz verwendet, es funktioniert gut (außer der Compiler mochte nicht "öffentliche Signale", es ist nur "Signale"), also vielen Dank! – houbysoft

Verwandte Themen