Gui Crash

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
honk0190
User
Beiträge: 9
Registriert: Dienstag 20. April 2010, 12:43

Hallo zusammen,

ich habe ein Problem bei dem handling von QThread. und zwar stürzt mir manchmal die Gui einfach ab und bekomme den Fehler:
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)

Hintergrund:
ich starte eine oberfläche und in der soll mit einem Thread etwas geschrieben werden.

Hier der Code:

Code: Alles auswählen

class MyGuiThread(QtCore.QThread):
    def __init__(self, dieGui,  derWorker):
        QtCore.QThread.__init__(self)
        self.darfLaufen=False
        self.dieGui= dieGui
        self.derWorker= derWorker

        
    def startStop(self):
        if self.darfLaufen:
            self.darfLaufen = False
            print "Ich halte MyGuiThread an"
            print "Ich halte MyWorkerThread an"
            #self.derWorker.killAll()
        else:
            self.darfLaufen=True
            print "Ich starte MyGuiThread"
            print "Ich starte MyWorkerThread"
            self.start()
            
    def run(self):

        n = 0
        step = 1
        while self.darfLaufen:
            n += step
            print n, "oder beliebige GUI Akionen, zb knopf aendern"
            # dazu muesste das Threadf Object das GUI Object erhalten
            # hier dann die aenderung an der gui, zb die werte gelesen und anzeigen o.ae.
            #self.derWorker.doChange()

            
            self.dieGui.area1.appendPlainText(str(n) +"\n")
            self.dieGui.area3.appendPlainText(str(n)+'\n')
            self.dieGui.area2.appendPlainText(str(n)+'\n')
            time.sleep(1)
in der main, rufe ich dann nur noch

Code: Alles auswählen

self.connect(self.uiRef.set, QtCore.SIGNAL("clicked()"), self.guithread.startStop)
auf und dann kommt der fehler.
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

das Problem ist, dass du von einem Thread auf die GUI zugreifst. Dies hat Qt nicht gerne.

Code: Alles auswählen

self.dieGui.area1.appendPlainText(str(n) +"\n")
Sende stattdessen ein Signal aus mit dem Text, der die View empfängt und darstellt.
honk0190
User
Beiträge: 9
Registriert: Dienstag 20. April 2010, 12:43

und wie sende ich ein signal mit dem text?
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

In etwa so:

Code: Alles auswählen

class MyGuiThread(QtCore.QThread):
    newText = QtCore.pyqtSignal(str)               # oder QString, hängt vom Gegenüber ab
    def __init__(self, dieGui,  derWorker):
...         
    def run(self):
        ...
        self.newText.emit('Text goes here')
franzf
User
Beiträge: 78
Registriert: Samstag 29. August 2009, 10:21

Ein SIGNAL setzt voraus, dass es auch connected ist, was nicht immer die schönste Lösung ist.
Man kann auch "direkt" eine Methode aus einem anderen Thread aufrufen, die dann in der Gui etwas zeichnet: via QMetaObject ;)
Dein Aufruf könnte dann so ausschauen:

Code: Alles auswählen

QMetaObject.invokeMethod(self.dieGui.area1, "appendPlainText", Qt.QueuedConnection, Q_ARG(QString, str(n)))
Wichtig ist die "QueuedConnection", da diese im Gegensatz zur directConnection gequeued wird ;) Das Ding kann dann nämlich später aus dem Gui-Thread heraus aufgerufen werden - denn QMetaObject.invokeMethod() macht Aufrufe über das Event-System.
lunar

@franzf: Das ist nichts anderes als eine Signal-Slot-Verbindung „ausgeschrieben“. Eine Signal-Slot-Verbindung ist eigentlich immer die schönere und sinnvollere Lösung, weil sie zusätzlich zur Thread-Sicherheit auch noch die Komponenten entkoppelt.
Antworten