问题
I have found a strange behavior if I create QThread as local variable.
For example, the following code will work as single thread, which means I need to wait 10 seconds and the result will come out.
But if I change thread from local variable to member variable, it works as multi thread.
How's it coming? Could anyone give me some tips?
class UI():
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.dialog = QtGui.QDialog()
self.ui = Ui_Dialog()
self.ui.setupUi(self.dialog)
self.ui.btn.clicked.connect(self.btnclick)
def run(self):
self.dialog.show()
sys.exit(self.app.exec_())
def btnclick(self):
## if change to self.thread, the behavior changes!!
signal = QtCore.SIGNAL("Log(QString)")
thread = testThread(signal)
QtCore.QObject.connect(thread, signal, self.output)
thread.start()
def output(self, txt):
self.ui.logText.append(str(txt))
class testThread(QThread):
def __init__(self, signal):
QThread.__init__(self)
self.signal = signal
def __del__(self):
self.wait()
def run(self):
for i in range(10):
time.sleep(1)
self.output(str(i))
def output(self, txt):
self.emit(self.signal, txt)
if __name__ == "__main__":
ui = UI()
ui.run()
回答1:
The problem as to point out is that it is a local variable that will be destroyed a moment after having started the QThread
so the thread that is handled by QThread
(QThread is not a thread, it is a thread handler) will be removed and when using wait()
it is expected that run()
method will be executed but in the main thread generating the GUI s freeze.
So the solution is to extend the life of the variable thread, one way you point out that it works: make it a member of the class, but there is another way that only works with QObjects as QThread and that is to pass a parent (the parent must to be another QObject) that will extend the life of the object to the same capacity of the parent, for that reason I will use a dialog.
Finally nowadays it is not recommended to create signals dynamically, it is better to create it as part of a class, also for the connection you must use the new syntax.
class UI():
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.dialog = QtGui.QDialog()
self.ui = Ui_Dialog()
self.ui.setupUi(self.dialog)
self.ui.btn.clicked.connect(self.btnclick)
self.dialog.show()
def btnclick(self):
thread = testThread(self.dialog)
thread.signal.connect(self.output)
thread.start()
def output(self, txt):
self.ui.logText.append(str(txt))
class testThread(QtCore.QThread):
signal = QtCore.pyqtSignal(str)
def __del__(self):
self.wait()
def run(self):
for i in range(10):
QtCore.QThread.sleep(1)
self.output(str(i))
def output(self, txt):
self.signal.emit(txt)
if __name__ == '__main__':
ui = UI()
app = QtGui.QApplication.instance()
if app is not None:
sys.exit(app.exec_())
来源:https://stackoverflow.com/questions/53443949/why-the-qthread-behave-different-if-create-it-as-local-variable