2015-09-05 118 views
1

我想了解PySide的線程化基礎知識,所以放在一起下面的代碼。我想要做的是啓動一個線程,它將使用字符串列表更新QPlainTextEdit小部件,每個字符串之間有一個延遲。相反,就是我得到的是一個崩潰到桌面,我不明白爲什麼:PySide:線程化導致GUI崩潰

import sys 
import time 

from PySide import QtCore, QtGui 

class Worker(QtCore.QThread): 

    to_log = QtCore.Signal(str) 

    def __init__(self, txt, parent=None): 
     super(Worker, self).__init__(parent) 

     self.txt = txt 

    def run(self): 

     for i in self.txt: 
      self.to_log.emit(i) 
      time.sleep(1) 


class TestThreadsApp(QtGui.QWidget): 

    def __init__(self): 
     super(TestThreadsApp, self).__init__() 

     self.initUI() 

    def initUI(self): 

     self.log = QtGui.QPlainTextEdit() 
     self.pb = QtGui.QPushButton('Go') 

     hbox = QtGui.QHBoxLayout() 
     hbox.addWidget(self.log) 
     hbox.addWidget(self.pb) 

     self.setLayout(hbox) 

     self.setGeometry(300, 300, 300, 150) 
     self.setWindowTitle('Test') 
     self.show() 

     self.pb.clicked.connect(self.get_worker) 

    def get_worker(self): 
     self.proceed = False 

     worker = Worker(['This is a test', 'to understand threading']) 
     worker.to_log.connect(self.to_log) 
     worker.start() 

    def to_log(self, txt): 
     self.log.appendPlainText(txt) 

def main(): 

    app = QtGui.QApplication(sys.argv) 
    ex = TestThreadsApp() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

如果我更新get_worker()方法下面,它將運行,但QPlainTextEdit部件與更新所有字符串同時,在這裏,因爲我想要的行爲是一個widget由每個字符串發出的線程進程更新 - 不完全後都已經發出:

def get_worker(self): 
     self.proceed = False 

     worker = Worker(['This is a test', 'to understand threading']) 
     worker.to_log.connect(self.to_log) 
     worker.start()   

     while not worker.isFinished(): 
      pass 
+0

我不知道PySide特別,但大多數的UI框架/工具包不是線程安全的,並要求用戶界面的任何更新到內發生主應用程序線程。 –

+0

@MichaelAaronSafyan。在Qt中通過線程發送信號是安全的(它們默認排隊),所以這不是問題。 – ekhumoro

回答

1

你需要保持一個引用該線程,否則只要get_worker返回就會被垃圾回收。

所以做這樣的事情,而不是:

def get_worker(self): 
     self.worker = Worker(['This is a test', 'to understand threading']) 
     self.worker.to_log.connect(self.to_log) 
     self.worker.start()   
+0

非常感謝,這個伎倆。我會記住這一點:垃圾收集。 – Groundhog