Seite 1 von 1

GUI mit Qt5 - Endlosschleife in Thread durch Button beenden

Verfasst: Dienstag 7. Januar 2020, 19:53
von salu44
Hallo zusammen,

ich habe folgendes Problem:
Parallel zu einem GUI läuft in einer Thread-Klasse eine Endlosschleife. Durch Drücken eines Buttons auf der GUI soll diese Endlosschleife beendet werden.

Meine Frage:
Wie kann ich durch einen Tastendruck auf den Thread zugreifen und die Endlosschleife beenden?

Ich wäre sehr dankbar für jeden Tipp:)
Grüße


Hier mein Beispielcode:

Code: Alles auswählen

import sys
from PyQt5.QtWidgets import QWidget, QAction, QMenu, QApplication, QMessageBox as QMB, QPushButton, QMainWindow
from PyQt5 import QtCore, QtWidgets
from PyQt5 import uic
import time
from PyQt5.QtCore import QThread, pyqtSignal, QObject



class Thread(QThread):
    # Create a counter thread

    change_text_btn = pyqtSignal(str)
    # text_status_Fehler_val = pyqtSignal(int, int)
    # text_status_Warnung_val = pyqtSignal(int, int)
    # text_status_val = pyqtSignal(int)
    # text_status = pyqtSignal(str)
    change_color_start_btn = pyqtSignal(str)
    # color_status_box = pyqtSignal(int, int)

    def __init__(self, *args):
        super(Thread, self).__init__()

        # Store constructor arguments (re-used for processing)

        self.args = args
        print(self.args[0])

    def run(self):

        x = 0
        z = 0

        endtime = time.time() + (self.args[0]/4) * 60


        while time.time() < endtime:
            x += 1
            print(x)
            time.sleep(0.01)


        time.sleep(0.5)
        self.change_text_btn.emit('Dauermessung läuft...')
        self.change_color_start_btn.emit('g')

        # Schleife soll durch Tastendruck beendet werden
        while 1:
            z+=1
            print(z)
            time.sleep(0.01)


class MainWindow(QMainWindow):

    def __init__(self):

        super().__init__()
        uic.loadUi('test_V1.ui', self)

        self.button_Einstellungen_uebernehmen.clicked.connect(self.Einstellungen_uebernehmen)
        self.button_start.clicked.connect(self.Messung_starten)
        self.status.clear()


    def Einstellungen_uebernehmen(self):
        '''Diese Funktion liest die Einstellungswerte vom GUI ein.'''

        self.einlaufzeit = int(self.comboBox_einlaufzeit.currentText())
        print(self.einlaufzeit)

        self.button_Einstellungen_uebernehmen.setStyleSheet("background-color: rgb(0,220,0)")


    def Messung_starten(self):

        self.thread = Thread(self.einlaufzeit)
        self.thread.change_text_btn.connect(self.setText_btn)
        # self.thread.text_status_Fehler_val.connect(self.setStatus_Fehler)
        # self.thread.text_status_Warnung_val.connect(self.setStatus_Warnung)
        # self.thread.text_status_val.connect(self.setStatus)
        # self.thread.text_status.connect(self.setText_Status)
        self.thread.change_color_start_btn.connect(self.color_start_btn)
        #self.thread.color_status_box.connect(self.color_checkbox)
        self.thread.start()


    def setText_btn(self, text_a):
        self.button_start.setText(text_a)


    def color_start_btn(self, color_a):
        if color_a == 'o':
            self.button_start.setStyleSheet("background-color: rgb(255,165,79)")
        elif color_a == 'g':
            self.button_start.setStyleSheet("background-color: rgb(0,220,0)")


    def closeEvent(self, ev):

        r = QMB.question(self, "Abfrage", "beenden?",
                         QMB.Yes | QMB.No, QMB.No)
        if r == QMB.Yes:
            ev.accept()
        else:
            ev.ignore()



def main():

    app = QApplication(sys.argv)  # A new instance of QApplication
    form = MainWindow()  # We set the form to be our ExampleApp (design)
    form.show()  # Show the form
    app.exec_()  # and execute the app


if __name__ == '__main__':  # if we're running file directly and not importing it
    main()  # run the main function

Re: GUI mit Qt5 - Endlosschleife in Thread durch Button beenden

Verfasst: Dienstag 7. Januar 2020, 21:14
von __deets__
Das gezeigte Muster durch Ableitung von threads ist veraltet und ungeschickt. Und beraubt dich der Möglichkeit, den Qt-Eigenen Mechanismus von Signal/slots wie er von mir zb hier viewtopic.php?t=44250&start=15 dargestellt wird zu nutzen. Und das ist auch der Weg, wie man Hintergrund-Threads etwas mitteilt.

Re: GUI mit Qt5 - Endlosschleife in Thread durch Button beenden

Verfasst: Mittwoch 8. Januar 2020, 16:50
von salu44
Vielen Dank für die Antwort!
Ich habe es jetzt so gelöst, dass die Schleife so lange läuft bis eine globale Variable x geändert wird. Ist vielleicht nicht die wirklich schön, aber funktioniert.
Grüße

Re: GUI mit Qt5 - Endlosschleife in Thread durch Button beenden

Verfasst: Mittwoch 8. Januar 2020, 17:25
von __blackjack__
@salu44: Das ist in der Tat nicht schön und ich sehe da auch gar keinen Grund für. Um einen QThread zu unterbrechen gibt es extra `requestInterruption()` und `isInterruptionRequestet()`.

Attrbute sollten alle nach Ablauf der `__init__()`-Methode angelegt werden und nicht irgendwann später noch hinzugefügt werden. Das macht Code nur unnötig unübersichtlich. Wenn man `thread` in der `__init__()` schon mit `None` initialisiert kann man auch testen ob bereits ein Thread läuft oder nicht. Man darf dann auch nicht vergessen nach Ende des Threads `thread` wieder an `None` zu binden.