In my code, when clicking a button (self.longRunningBtn) it connects to a function that takes no parameters and it works fine. When that function is modified to take extra parameters a, b, c i get an error TypeError: argument 1 has unexpected type 'NoneType'. This is then fixed by adding lambda to the call but now the function doesn't seem to run at all and the entire GUI freezes even though it is on a different thread. I would like to be able to click self.longRunningBtn with parameters a, b, c without seeing that error and without the GUI freezing.
Original code without parameters, works perfectly:
from PyQt5.QtCore import QObject, QThread, pyqtSignal
import sys
from time import sleep
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QApplication,
QLabel,
QMainWindow,
QPushButton,
QVBoxLayout,
QWidget,
)
class Worker(QObject):
finished = pyqtSignal()
progress = pyqtSignal(str)
def run(self):
for i in range(5):
sleep(1)
self.progress.emit(f"{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}")
def runLongTask(self):
# Step 2: Create a QThread object
self.thread = QThread()
# Step 3: Create a worker object
self.worker = Worker()
self.worker.moveToThread(self.thread)
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())
Code with parameters added:
def run(self, a, b, c):
for i in range(5):
sleep(1)
self.progress.emit(f"{i+1} {a} {b} {c}")
self.finished.emit()
self.thread.started.connect(self.worker.run("alpha", "beta", "charlie"))
returns TypeError: argument 1 has unexpected type 'NoneType'
Fix for TypeError:
self.thread.started.connect(lambda: self.worker.run("alpha", "beta", "charlie"))
But now the GUI freezes and I can't see anything that the function is doing, I would like it to function exactly as in the original code but with a, b, c attached to the end of the label as well.