2012-08-28 34 views
2

我在我的程序 的「主」線程中創建了一個QTextEdit組件,然後我啓動另一個線程,它將每隔x秒更新一次QTextEdit,但隨後出現此錯誤:如何在pyQt4中的不同線程中清除QTextEdit

QObject: Cannot create children for a parent that is in a different thread. 

這是我做的方式:

def initGui(): 
    #some gui components 
    global txt_list 

    txt_list = QtGui.QTextEdit(w) 
    txt_list.resize(580,400) 
    txt_list.move(50, 50) 
    txt_list.setReadOnly(1) 
    txt_list.setFont(font_consolas) 
    #more gui components 

def update_list(): 
    t_monitor = threading.Thread(target=monitor_vector) 
    t_monitor.daemon = True 
    t_monitor.setName('monitor') 
    t_monitor.start() 

def monitor_vector(): 
    #retrieve info... 
    lock = threading.Lock 
    lock = True 
    txt_list.clear() #clear list, to set the new one 
    txt_list.setText('updated list') 
    lock = False 

代碼這最後兩句給我上面提到的錯誤。有人可以給我一個線索如何處理這個問題嗎?

謝謝!

回答

5

關於Qt的一個主要問題是,你不能從主GUI線程以外的任何線程調用任何QWidget方法。所有的溝通都必須通過發送額外線程的信號來完成,這些線程將轉發給主要的gui。

首先,我看到您使用的是全局變量,並且缺少關鍵字self,所以我假定您沒有使用類。我的例子也將包含一個類的例子。

這是例子是裸露的筋骨,就像你的,你勾勒可能要採取的方向:

from PyQt4 import QtGui, QtCore 

class MyWidget(QtGui.QWidget): 

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

     ... 
     self.txt_list = QtGui.QTextEdit(self) 
     self.txt_list.resize(580,400) 
     self.txt_list.move(50, 50) 
     self.txt_list.setReadOnly(1) 
     self.txt_list.setFont(font_consolas) 
     ... 
     self.monitor = Monitor() 
     self.monitor.updateText.connect(self._handleTextUpdate) 
     self.monitor.update_list() 

    def _handleTextUpdate(self, txt): 
     self.txt_list.clear() 
     self.txt_list.setText(txt) 


class Monitor(QtCore.QObject): 

    updateText = QtCore.pyqtSignal(str) 

    def update_list(self): 
     t_monitor = Thread(self.monitor_vector, parent=self) 
     t_monitor.daemon = True 
     t_monitor.setName('monitor') 
     t_monitor.start() 

    def monitor_vector(self): 
     ... 
     self.updateText.emit('updated list') 


class Thread(QtCore.QThread): 

    def __init__(self, fn, args, kwargs, parent=None): 
     super(Thread, self).__init__(parent) 
     self._fn = fn 
     self._args = args 
     self._kwargs = kwargs 

    def run(self): 
     self._fn(*self._args, **self._kwargs) 

要注意的主要事情是,在線程中運行的功能被髮射的信號。他們不瞭解其他類中的QWidgets。您的MyWidget類將信號連接到可更新QLineEdit的插槽。當線程發出信號時,它將排隊進入主線程並由接收槽執行。

我還創建了一個簡單的QThread子類,它可以採用函數和參數,複製標準庫Thread類的工作方式。你應該堅持使用QThread,因爲它是一個QObject子類,並且支持信號並且可以運行事件循環。

+0

我是這樣做的,得到了​​: TypeError:pyqtSignal必須綁定到一個QObject,而不是'實例' – RicardoE

+0

您是否確定將它作爲類屬性和** NOT **放入您的'__init__' ? – jdi

+0

是的,最後我發現我的錯誤,我在主類中宣佈了信號......現在它像一種魅力一樣工作,感謝很多朋友,你必須在這裏幫助! – RicardoE

相關問題