ich versuche mich an einer GUI für einen Dateidownload. Wie zu erwarten friert die GUI wärend des Downloads ein. Habe dann hier im Forum gestöbert und bin in einem Thread auf diesen Link gestoßen https://realpython.com/python-pyqt-qthread/. Ich verstehe die dort geschilderte Funktionsweise mit dem auslagern des 'Long running task' in einen Worker-Thread und die Signale von dort zurück in den Window Thread.
Was mir nicht einleuchtet, wie schicke ich Signale vom Window Thread an den Worker Thread? Ich verstehe das senden ansich schon, nur werden die Slots im Window Thread in Methoden abgearbeitet. Der Worker-Thread hat aber nur die 'run()' Methode, in der der 'Long running task' läuft. Kann ich da auch beliebig neue Methoden erstellen?
Um meine Frage zu veranschaulichen, hier mal der Code aus dem Link oben.
Wenn ich nun in der Worker Klasse das "for i in range(5)" in ein "for i in range(x)" umschreiben möchte und dann das x aus der Window Klasse an die Worker Klasse übergeben möchte, wie mache ich das?
Code: Alles auswählen
import sys
from time import sleep
from PyQt5.QtCore import QObject, QThread, pyqtSignal
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
    QApplication,
    QLabel,
    QMainWindow,
    QPushButton,
    QVBoxLayout,
    QWidget,
)
# Step 1: Create a worker class
class Worker(QObject):
    finished = pyqtSignal()
    progress = pyqtSignal(int)
    def run(self):
        """Long-running task."""
        for i in range(5):
            sleep(1)
            self.progress.emit(i + 1)
        self.finished.emit()
class Window(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.clicksCount = 0
        self.setupUi()
    def setupUi(self):
        self.setWindowTitle("Freezing GUI")
        self.resize(300, 150)
        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)
        
        # Create and connect widgets
        self.clicksLabel = QLabel("Counting: 0 clicks", self)
        self.clicksLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.stepLabel = QLabel("Long-Running Step: 0")
        self.stepLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.countBtn = QPushButton("Click me!", self)
        self.countBtn.clicked.connect(self.countClicks)
        self.longRunningBtn = QPushButton("Long-Running Task!", self)
        self.longRunningBtn.clicked.connect(self.runLongTask)
        
        # Set the layout
        layout = QVBoxLayout()
        layout.addWidget(self.clicksLabel)
        layout.addWidget(self.countBtn)
        layout.addStretch()
        layout.addWidget(self.stepLabel)
        layout.addWidget(self.longRunningBtn)
        self.centralWidget.setLayout(layout)
    def countClicks(self):
        self.clicksCount += 1
        self.clicksLabel.setText(f"Counting: {self.clicksCount} clicks")
    def reportProgress(self, n):
        self.stepLabel.setText(f"Long-Running Step: {n}")
        # Snip...
    def runLongTask(self):
        # Step 2: Create a QThread object
        self.thread = QThread()
        # Step 3: Create a worker object
        self.worker = Worker()
        # Step 4: Move worker to the thread
        self.worker.moveToThread(self.thread)
        # Step 5: Connect signals and slots
        self.thread.started.connect(self.worker.run)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.progress.connect(self.reportProgress)
        
        # Step 6: Start the thread
        self.thread.start()
        # Final resets
        self.longRunningBtn.setEnabled(False)
        self.thread.finished.connect(
            lambda: self.longRunningBtn.setEnabled(True)
        )
        self.thread.finished.connect(
            lambda: self.stepLabel.setText("Long-Running Step: 0")
        )
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())
