2015-09-05 116 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