2014-09-20 52 views
0

下面是代碼:爲什麼我不能在類的成員函數中初始化QThread?

########################################################## 
######## Version 1 (works) 
########################################################## 
#!/usr/bin/env python3 


from ui.qthreadtest import Ui_QthreadTest 
from PySide import QtCore, QtGui 
import time 

class Md(QtGui.QDialog): 
    def __init__(self): 
     super().__init__() 
     self.prcsbtn = QtGui.QPushButton("Process") 
     self.prcsedit = QtGui.QLineEdit() 
     layout = QtGui.QHBoxLayout() 
     layout.addWidget(self.prcsedit) 
     layout.addWidget(self.prcsbtn) 
     self.setLayout(layout) 
     self.prcsbtn.clicked.connect(self.work) 

     self.wt = Worker() 

    def work(self): 
     self.wt.start() 
     # the DirectConnection option demands the slot to be triggered immediately 
     self.wt.workFinished.connect(self.changeText, QtCore.Qt.DirectConnection) 

    def changeText(self): 
     self.prcsedit.setText("Work finished!") 

class Worker(QtCore.QThread): 
    workFinished = QtCore.Signal() 
    def __init__(self): 
     super().__init__() 

    def run(self): 
     time.sleep(2) 
     self.workFinished.emit() 

import sys 
app = QtGui.QApplication(sys.argv) 
md = Md() 
md.show() 
sys.exit(app.exec_()) 


########################################################## 
######## Version 2 (doesn't work)  
########################################################## 

#!/usr/bin/env python3 


from ui.qthreadtest import Ui_QthreadTest 
from PySide import QtCore, QtGui 
import time 

class Md(QtGui.QDialog): 
    def __init__(self): 
     super().__init__() 
     self.prcsbtn = QtGui.QPushButton("Process") 
     self.prcsedit = QtGui.QLineEdit() 
     layout = QtGui.QHBoxLayout() 
     layout.addWidget(self.prcsedit) 
     layout.addWidget(self.prcsbtn) 
     self.setLayout(layout) 
     self.prcsbtn.clicked.connect(self.work) 


    def work(self): 
     # the worker thread initialized in a member function won't work. 
     wt = Worker() 
     wt.start() 
     # the DirectConnection option demands the slot to be triggered immediately 
     wt.workFinished.connect(self.changeText, QtCore.Qt.DirectConnection) 

    def changeText(self): 
     self.prcsedit.setText("Work finished!") 

class Worker(QtCore.QThread): 
    workFinished = QtCore.Signal() 
    def __init__(self): 
     super().__init__() 

    def run(self): 
     time.sleep(2) 
     self.workFinished.emit() 

import sys 
app = QtGui.QApplication(sys.argv) 
md = Md() 
md.show() 
sys.exit(app.exec_()) 

1件作品OK,版本2給出了這樣的錯誤(而破碎瞬間,當處理按鈕被按下):

QThread: Destroyed while thread is still running 

Process finished with exit code 139 
+0

錯誤消息幾乎無法使事情更加明顯,尤其是因爲這兩個例子之間的唯一真正的區別在於一個保持對工人的引用線程,而另一個沒有。另外,你應該知道使用[直接連接信號是不安全的](https://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-線程)。 – ekhumoro 2014-09-20 17:50:54

回答

2

發生這種情況,因爲不像threading.Thread對象,QThread對象一旦超出範圍就會被銷燬。在你的例子中,當work結束時wt超出範圍,因此對象被破壞。爲了避免這種情況,您需要持續參考wt。這樣做的一個方法是使一個實例變量:

def work(self): 
    self.wt = Worker() 
    self.wt.start() 
    # the DirectConnection option demands the slot to be triggered immediately 
    self.wt.workFinished.connect(self.changeText, QtCore.Qt.DirectConnection) 
相關問題