Reputation: 2353
I am a PyQt 5.4.1-1
beginner, my python is 3.4.3
. Here is my attempt to follow the many blogposts and SO questions on the proper ™ way to make a thread (i.e. no QThread subclassing):
#!/usr/bin/env python3
from PyQt5.QtCore import QObject, QThread
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
print("Base init")
self.thread = QThread()
w = Worker()
w.finished[int].connect(self.onFinished)
w.moveToThread(self.thread)
self.thread.started.connect(w.work)
self.thread.start()
@pyqtSlot(int)
def onFinished(self, i):
print("Base caught finished, {}".format(i))
class Worker(QObject):
finished = pyqtSignal(int)
def __init__(self):
print("Worker init")
super().__init__()
def work(self):
print("Worker work")
Worker.finished.emit(42)
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
While writing this question, I realised that if the following changes are made, then it all seems to work:
...
self.w = Worker()
self.w.finished[int].connect(self.onFinished)
self.w.moveToThread(self.thread)
self.thread.started.connect(self.w.work)
...
...
self.finished.emit(42)
...
But I do not understand why this helps. Why do I have to make a non-Gui related Worker
instance a member of the Gui class? Feels wrong, frankly. And now about the signal: it's a class attribute so why is there a difference between calling Worker.finished.emit(42)
which fails at runtime and a self.finisehd.emit(42)
which succeeds when I would expect no difference (it's a class attribute!)
Upvotes: 3
Views: 7952
Reputation: 774
First, Python is an automatically garbage collected language. Your variable w
goes out of scope in the __init__
method, and is promptly garbage collected after the method returns. This is why things did not work out the way you expected the first time. Making the variable a member of the class makes sure that it does not go out of scope while the MainWindow
instance exists.
Your second question is a bit harder to answer, but I bet you will gain valuable insight into how signals work in PySide/PyQt by looking at the QMetaObject documentation.
--EDIT--
Found a better answer for your second question here.
Upvotes: 1