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())