2014-05-25 73 views
0

我正在嘗試執行pyqt線程的基本示例,其中有一個文本框在處理某些代碼時定期更新。我試圖刪除任何不必要的依賴項並儘可能地提取代碼,所以我簡單地用後臺處理的代碼替換爲每個循環發送數據的while循環以供文本框讀取。然而,它不工作,我不知道是什麼導致UI掛斷。我添加調試當前線程ID和主和工人類的語句(在我的例子,它被稱爲進程)並匹配Qthread無法正常工作,GUI仍然掛起

#!/zin/tools/bin/python 
#vim:expandtab filetype=python nocindent sw=4 

import sys, traceback 
import os 
import subprocess 
import time 
from PyQt4 import QtCore,QtGui 


try: 
    _fromUtf8 = QtCore.QString.fromUtf8 
except AttributeError: 
    _fromUtf8 = lambda s: s 

class Process (QtCore.QObject): 
    processCmdDone = QtCore.pyqtSignal() 
    processdataReady = QtCore.pyqtSignal(str) 

    def __init__(self): 
     super(Process, self).__init__() 
     self.processdataReady.connect(self.debug) 

    def debug(self): 
     print "signal process data ready is invoked from within the process" 

    @QtCore.pyqtSlot() 
    @QtCore.pyqtSlot(str) 
    def execCmd(self): 
     print 'worker thread id :'+ str (QtCore.QThread.currentThreadId()) 
     x = 0 
     while x < 100: 
      x+=1 
      self.processdataReady.emit(str(x)+'\n') 
      time.sleep(1) 
     self.processCmdDone.emit() 
     print "process ended" 


class MainWindow (QtGui.QWidget): 
    def __init__(self,filename = None, parent=None): 
     super(MainWindow,self).__init__(parent) 
     self.transcript_textEdit = QtGui.QTextBrowser() 
     font = QtGui.QFont() 
      font.setPointSize(12) 
      self.transcript_textEdit.setFont(font) 
      self.transcript_textEdit.setObjectName(_fromUtf8("transcript_textEdit")) 
      self.layout = QtGui.QVBoxLayout(self) 
      self.layout.addWidget(self.transcript_textEdit) 

     self.run_pushButton = QtGui.QPushButton() 
      self.run_pushButton.setFont(font) 
      self.run_pushButton.setObjectName(_fromUtf8("run_pushButton")) 
      self.run_pushButton.setText('Run') 
      self.layout.addWidget(self.run_pushButton) 
      self.run_pushButton.clicked.connect(self.execCmdThreading) 

    def dataReady(self,text): 

     cursor = self.transcript_textEdit.textCursor() 
     cursor.movePosition(cursor.End) 
     cursor.insertText(str(text)) 
     self.transcript_textEdit.ensureCursorVisible() 


    def execCmdThreading(self): 
     print 'gui thread id :'+ str (QtCore.QThread.currentThreadId()) 
     thread = QtCore.QThread(self) 
     process_inst = Process() 
     process_inst.moveToThread(thread) 
     process_inst.processdataReady.connect(self.dataReady) 
     process_inst.processCmdDone.connect(thread.quit) 
     thread.finished.connect(thread.deleteLater) 
     process_inst.processCmdDone.connect(process_inst.deleteLater) 
     thread.started.connect(lambda: process_inst.execCmd()) 
     thread.start() 



if __name__=="__main__": 
    import sys 
    app = QtGui.QApplication(sys.argv) 
    MainWindowInst = MainWindow() 
    MainWindowInst.show() 
    sys.exit(app.exec_()) 

我簡單地創建一個文本框和按鈕,其中上點擊按鈕一線程是爲類'Process'的inst創建的,其中moveToThread和它的方法'execCmd'被執行。在執行execCmd方法時,會發出一個信號「processdataReady」,預期會在創建的文本框中顯示文本。然而,代碼似乎沒有按預期運行,並且用戶界面確實掛起。

我真的很感謝任何人的幫助。

回答

1

你的thread.started信號連接到拉姆達:

thread.started.connect(lambda: process_inst.execCmd()) 

使用例正常蟒蛇調用這裏總會引起GUI線程要處理的信號。這是可以理解的,因爲可調用對象(lambda)沒有QObject擁有的線程關係。然後從lambda內部同步執行process_inst.execCmd方法,這與對象具有的線程親和性無關。因此GUI線程會阻塞。

如果您希望在工作線程事件lopp內接收並處理信號,請直接將其連接到插槽。

爲了達到此目的,您還需要確保您保留對process_inst的引用,否則它將在超出範圍時被銷燬。

有了這些調整你的程序爲我工作:

... 
thread.started.connect(process_inst.execCmd) 
thread.process_inst = process_inst 
... 
+0

非常感謝,也沒有工作......終於:)))) – user3660964

相關問題