Seite 1 von 1

Funktionen aus Thread starten (QtWidget Methode)

Verfasst: Mittwoch 31. Oktober 2018, 10:00
von Tinker232
Hallo zusammen,

ich möchte gerne eine Methode starten, die optische Merkmale auf meiner grafischen Oberfläche setzt, wie z.B. Progress_Bar.setValue(0)

Hintergrund ist:
Ich habe einen Thread der Daten schreibt. Während dieser Zeit sind diverse Elemente auf meinem GUI gesperrt, wie z.B. ein Slider.
Drücke ich nun den Stop_Button wird innerhalb des Threads die Schleife beendet und die restlichen Daten werden geschrieben, bis meine Queue leer ist.
Erst dann sollen die Elemente auf dem GUI wieder freigegeben werden bzw. die Progress_Bar auf 0 gesetzt werden.
Um meine Elemente erst dann freizugeben wenn der Thread auch beendet ist, wollte ich die Funktion "setze_style_gui" direkt aus dem Thread starten, bevor er sich beendet. Also als letzte Amtshandlung des Threads sozusagen.
Praktisch gesehen funktioniert das auch in den meisten Fällen, jedoch habe ich gelesen, dass Veränderungen von QWidgets aus einem Thread nicht threadsafe sind und massive Probleme verursachen können.
Nach etlichen Versuchen hatte ich dann auch einen kompletten Absturz mit der Meldung:

Code: Alles auswählen

QWidget::repaint: Recursive repaint detected.
Jetzt ist meine Frage...
Wie kann ich aus meinem Thread die Funktion "setze_style_gui" starten, die sich in meinem Mainloop (GUI) befindet. Die Funktion enthält Methoden von QWidgets!

Code: Alles auswählen

def setze_style_gui(self, is_standby):
self.is_standby = is_standby
if self.is_standby:
   self.label_1.setText...
   self.label_2.setStyleSheet ...
   self.schieber.setEnable(True)
   self.Progress_Bar.setValue(0)
else:
   self.label_1.setText...
   self.label_2.setStyleSheet ...
   self.schieber.setDisabled(True)
   
   # Thread #
... Schleife zum Schreiben der Daten...
... Wenn Queue leer ist dann, Schleife abbrechen..
   self.setze_style_standby(True)
Kann ich das mit Signalen & Slots irgendwie abbilden? Ich habe ja hier kein Widget was das Signal sendet wie einen Button oder ähnliches?
Danke LG Tina

Re: Funktionen aus Thread starten (QtWidget Methode)

Verfasst: Mittwoch 31. Oktober 2018, 10:08
von __blackjack__
@Tinker232: Signale kann jedes QObject senden, das muss kein Widget sein. Du kannst also auch in einem von QObject abgeleiteten Objekt ein Signal definieren das Du dann sendest wenn zum Beispiel die Aufgabe zuende abgearbeitet ist.

Re: Funktionen aus Thread starten (QtWidget Methode)

Verfasst: Mittwoch 31. Oktober 2018, 10:53
von Tinker232
Das bedeutet jedoch, dass ich zuvor ein QObject erzeugen müsste. Ich habe in dem Thread kein QObject welches mein Signal emitten könnte, oder?

Re: Funktionen aus Thread starten (QtWidget Methode)

Verfasst: Mittwoch 31. Oktober 2018, 11:03
von __blackjack__
@Tinker232: Da ich den Code nicht kenne weiss ich nicht ob Du so ein Objekt hast, aber man würde sich ja auch eher speziell dafür ein eigenes Signal definieren. Wobei `QThread` vielleicht einen Blick wert ist. An der Stelle ist dann immer die Frage wie weit man die Programmlogik von Qt abhängig machen möchte, oder ob das grundsätzlich Teile sind, die auch ohne Qt laufen können sollen. Im letzteren Fall könnte man auch eine Rückruffunktion in den eigenen Code einbauen und über die dann die Verbindung zu Qt-spezifischem Code schlagen, also beispielsweise mit einer von QObject abgeleitete Klasse mit einem Signal. Wobei man da eventuell auch schon eine passende Klasse hat, die man nur durch eine Signaldefinition erweitern muss.

Re: Funktionen aus Thread starten (QtWidget Methode)

Verfasst: Mittwoch 31. Oktober 2018, 12:06
von __deets__
Du solltest QThread verwenden. Denn dadurch erst kann das senden von Signalen thread-sicher erfolgen. Dazu prueft Qt, ob der Sender eines Signals dem gleichen Thread wie der Empfaenger. Wenn dem nicht so ist, dann benutzt es sogenannte "Queued Connections", die in den mainloop des Empfaengerthreads eingetuetet werden, und da dann sicher ihre Wirkung entfalten koennen.

Und ein QObject einzufuehren ist ja nun nur wenige Zeilen Code. Ggf. kommst du dank pyqt da aber auch drumrum, denn Phil hat ja Unterstuetzung fuer alleinstehende Funktionen, lambdas etc eingebaut.

Nachtrag: wenn du deinen Thread einen QThread machst, dann *hast* du ein QObject. Normalerweise macht man aber noch ein explizites worker-Object.

Re: Funktionen aus Thread starten (QtWidget Methode)

Verfasst: Mittwoch 31. Oktober 2018, 12:33
von Tinker232
Hallo zusammen, danke für die Hinweise...
Ich habe es nun mittels eigenem Signal / Slot erledigt -> http://zetcode.com/gui/pyqt5/eventssignals/
Funktioniert Prima so!
Danke nochmal
LG