2012-05-22 89 views
3

我試圖通過在PyQt中的QThread更新Qt GUI對象中的文本,但我剛剛得到錯誤QPixmap: It is not safe to use pixmaps outside the GUI thread,然後它崩潰。我非常感謝任何幫助,謝謝。PyQt更新gui

class MainWindow(QMainWindow, Ui_MainWindow): 

    def __init__(self, parent = None): 
     QMainWindow.__init__(self, parent) 
     self.setupUi(self) 
     self.output = Output() 

    def __del__ (self): 
     self.ui = None 

    @pyqtSignature("") 
    def on_goBtn_released(self): 
     threadnum = 1 
     #start threads 
     for x in xrange(threadnum): 
      thread = TheThread() 
      thread.start() 


class Output(QWidget, Ui_Output): 

    def __init__(self, parent = None): 
     QWidget.__init__(self, parent) 
     self.setupUi(self) 
     self.ui = Ui_Output 
     self.show() 

    def main(self): 
     self.textBrowser.append("sdgsdgsgsg dsgdsg dsgds gsdf") 



class TheThread(QtCore.QThread): 

    trigger = pyqtSignal() 

    def __init__(self): 
     QtCore.QThread.__init__(self) 

    def __del__(self): 
     self.wait() 

    def run(self): 
     self.trigger.connect(Output().main()) 
     self.trigger.emit() 

回答

8
self.trigger.connect(Output().main()) 

這條線是有問題的。您正在線程中實例化一個類,它看起來像一個小部件。這是錯誤的。您不應該在不同的線程中使用GUI元素。所有與GUI相關的代碼應該與事件循環在同一個線程中運行。

上述線在設計方面也是錯誤的。你從你的線程發出一個自定義信號,這是一個好方法。但處理此信號的對象應該是擁有/創建線程的對象,即您的MainWindow

您也不保留對線程實例的引用。你在一個方法中創建它,但它是本地的。所以它會被垃圾收集,你可能會看到一個警告,說它在完成之前被刪除。

這裏是一個最小的工作例如:

import sys 
from PyQt4 import QtGui, QtCore 
import time 
import random 


class MyThread(QtCore.QThread): 
    trigger = QtCore.pyqtSignal(int) 

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

    def setup(self, thread_no): 
     self.thread_no = thread_no 

    def run(self): 
     time.sleep(random.random()*5) # random sleep to imitate working 
     self.trigger.emit(self.thread_no) 


class Main(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(Main, self).__init__(parent) 
     self.text_area = QtGui.QTextBrowser() 
     self.thread_button = QtGui.QPushButton('Start threads') 
     self.thread_button.clicked.connect(self.start_threads) 

     central_widget = QtGui.QWidget() 
     central_layout = QtGui.QHBoxLayout() 
     central_layout.addWidget(self.text_area) 
     central_layout.addWidget(self.thread_button) 
     central_widget.setLayout(central_layout) 
     self.setCentralWidget(central_widget) 

    def start_threads(self): 
     self.threads = []    # this will keep a reference to threads 
     for i in range(10): 
      thread = MyThread(self) # create a thread 
      thread.trigger.connect(self.update_text) # connect to it's signal 
      thread.setup(i)   # just setting up a parameter 
      thread.start()    # start the thread 
      self.threads.append(thread) # keep a reference 

    def update_text(self, thread_no): 
     self.text_area.append('thread # %d finished' % thread_no) 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 

    mainwindow = Main() 
    mainwindow.show() 

    sys.exit(app.exec_()) 
+0

,完美的工作,非常感謝你! – amba88