2015-09-23 33 views
0

我写了简单的Python脚本,但我遇到了问题。我想运行一个没有阻塞GUI(使用线程)的函数,并且该函数有多个线程。最后它会产生2种错误。首先是在Python的主线程中使用多线程

QObject::connect: Cannot queue arguments of type 'QTextCursor' (Make sure 'QTextCursor' is registered using qRegisterMetaType().) 

二是

Segmentation fault (core dumped) 

在我的剧本我找不到错误。出了什么问题?

form.py

from PyQt4 import QtCore, QtGui 

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
     MainWindow.setObjectName("MainWindow") 
     MainWindow.resize(956, 395) 
     self.centralwidget = QtGui.QWidget(MainWindow) 
     self.centralwidget.setObjectName("centralwidget") 
     self.horizontalLayoutWidget = QtGui.QWidget(self.centralwidget) 
     self.horizontalLayoutWidget.setGeometry(QtCore.QRect(230, 30, 716, 251)) 
     self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") 
     self.horizontalLayout = QtGui.QHBoxLayout(self.horizontalLayoutWidget) 
     self.horizontalLayout.setObjectName("horizontalLayout") 
     self.textEdit_2 = QtGui.QTextEdit(self.horizontalLayoutWidget) 
     self.textEdit_2.setObjectName("textEdit_2") 
     self.horizontalLayout.addWidget(self.textEdit_2) 
     self.textEdit_3 = QtGui.QTextEdit(self.horizontalLayoutWidget) 
     self.textEdit_3.setObjectName("textEdit_3") 
     self.horizontalLayout.addWidget(self.textEdit_3) 
     self.textEdit_4 = QtGui.QTextEdit(self.horizontalLayoutWidget) 
     self.textEdit_4.setObjectName("textEdit_4") 
     self.horizontalLayout.addWidget(self.textEdit_4) 
     self.textEdit_5 = QtGui.QTextEdit(self.horizontalLayoutWidget) 
     self.textEdit_5.setObjectName("textEdit_5") 
     self.horizontalLayout.addWidget(self.textEdit_5) 
     self.textEdit_6 = QtGui.QTextEdit(self.horizontalLayoutWidget) 
     self.textEdit_6.setObjectName("textEdit_6") 
     self.horizontalLayout.addWidget(self.textEdit_6) 
     self.textEdit_7 = QtGui.QTextEdit(self.horizontalLayoutWidget) 
     self.textEdit_7.setObjectName("textEdit_7") 
     self.horizontalLayout.addWidget(self.textEdit_7) 
     self.textEdit_8 = QtGui.QTextEdit(self.horizontalLayoutWidget) 
     self.textEdit_8.setObjectName("textEdit_8") 
     self.horizontalLayout.addWidget(self.textEdit_8) 
     self.textEdit_9 = QtGui.QTextEdit(self.horizontalLayoutWidget) 
     self.textEdit_9.setObjectName("textEdit_9") 
     self.horizontalLayout.addWidget(self.textEdit_9) 
     self.table = QtGui.QTableWidget(self.centralwidget) 
     self.table.setGeometry(QtCore.QRect(10, 30, 211, 291)) 
     self.table.setObjectName("table") 
     self.table.setColumnCount(2) 
     self.table.setRowCount(0) 
     item = QtGui.QTableWidgetItem() 
     self.table.setHorizontalHeaderItem(0, item) 
     item = QtGui.QTableWidgetItem() 
     self.table.setHorizontalHeaderItem(1, item) 
     self.button = QtGui.QPushButton(self.centralwidget) 
     self.button.setGeometry(QtCore.QRect(120, 330, 85, 27)) 
     self.button.setObjectName("button") 
     self.button_2 = QtGui.QPushButton(self.centralwidget) 
     self.button_2.setGeometry(QtCore.QRect(10, 330, 85, 27)) 
     self.button_2.setObjectName("button_2") 
     self.log = QtGui.QTextEdit(self.centralwidget) 
     self.log.setGeometry(QtCore.QRect(230, 290, 361, 71)) 
     self.log.setObjectName("log") 
     MainWindow.setCentralWidget(self.centralwidget) 
     self.statusbar = QtGui.QStatusBar(MainWindow) 
     self.statusbar.setObjectName("statusbar") 
     MainWindow.setStatusBar(self.statusbar) 

     self.retranslateUi(MainWindow) 
     QtCore.QObject.connect(self.button_2, QtCore.SIGNAL("clicked()"), MainWindow.close) 
     QtCore.QMetaObject.connectSlotsByName(MainWindow) 

    def retranslateUi(self, MainWindow): 
     MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) 
     self.table.horizontalHeaderItem(0).setText(QtGui.QApplication.translate("MainWindow", "no", None, QtGui.QApplication.UnicodeUTF8)) 
     self.table.horizontalHeaderItem(1).setText(QtGui.QApplication.translate("MainWindow", "status", None, QtGui.QApplication.UnicodeUTF8)) 
     self.button.setText(QtGui.QApplication.translate("MainWindow", "Run", None, QtGui.QApplication.UnicodeUTF8)) 
     self.button_2.setText(QtGui.QApplication.translate("MainWindow", "Close", None, QtGui.QApplication.UnicodeUTF8)) 

main.py

from form import * 
import time 
import threading 
import os 
from subprocess import call 
import Queue 


class mainWindow(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     QtGui.QWidget.__init__(self,parent) 
     self.ui = Ui_MainWindow() 
     self.ui.setupUi(self) 
     self.ui.table.verticalHeader().setVisible(False) 
     for i in range(2,10): 
      item = QtGui.QTableWidgetItem(str(i)) 
      item2 = QtGui.QTableWidgetItem("Ready") 
      item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled) 
      item.setCheckState(QtCore.Qt.Unchecked) 
      self.ui.table.setRowCount(i-1) 
      self.ui.table.setItem(i-2, 0, item) 
      self.ui.table.setItem(i-2, 1, item2) 
     #:for 
     QtCore.QObject.connect(self.ui.button , QtCore.SIGNAL("clicked()"), self.callback_runButton) 
    #:def 

    def callback_runButton(self): 
     numList = [] 
     for i in range(0,self.ui.table.rowCount()): 
      if self.ui.table.item(i,0).checkState() == 2 and str(self.ui.table.item(i,1).text()) == 'Ready': 
       print self.ui.table.item(i,0).text() 
       self.ui.table.item(i,1).setText('Run')   
       numList.append(i) 
      #if 
     #:for 

     #### Question 1:   
     #1. I want to no blocking GUI under runnig "self.run_MultiplicationTable(numList)" 
     #2. although called "self.run_MultiplicationTable(numList)", I Want to run function again. 
     #3. I try to thread function. but #2 is not permit. (GUI is not blocking, but function is not excuted.) 
     #4. I try to process(run fuction under child process), but I can't modify GUI(parent process). 

     #self.run_MultiplicationTable(numList) 
     th = Run_MultiplicationTable(self,numList) 
     th.start() 
    #:def  

    def run_MultiplicationTable(self, numList): 
     print "Run_MultiplicationTable" 
     for i in numList: 
      #### Question 2: smilay Question 1 
      #1. I want to run under function at same time. 
      self.each_Cal(i) 
     #:for 
    #def 
    def each_Cal(self, num): 
     i = self.ui.table.item(num,0).text() 
     putTextEdit = eval('self.ui.textEdit_'+ str(i)) 
     for j in range(1,10): 
      printString = str(i)+' * '+str(j)+'='+str(int(i)*j)  
      putTextEdit.append(printString) 
      time.sleep(1) #It is job excuted time 
     #:for 
     self.ui.table.item(num,1).setText('Done') 

    #def 
#:class 

class Run_MultiplicationTable(threading.Thread): 
    def __init__(self, mainWin,numList ,daemon=True, parent=None): 
     threading.Thread.__init__(self) 
     self.mainWin = mainWin 
     self.daemon = daemon 
     self.numList = numList 
    #def 

    def run(self): 
     thList = [] 
     for num in self.numList: 
      q = Queue.Queue() 
      th2 = Run_Each(self.mainWin, num,q) 
      th2.start() 
      thList.append([q,th2]) 
     #:for 

     #Check close of all sub-thread. 
     while True: 
      isRun = False 
      for i in thList: 
       print str(i[1])+' '+str(i[1].is_alive()) 
       isRun = isRun or i[1].is_alive() 
       if i[1].is_alive() : 
        getVal = i[0].get() 
        print "End 1ea sub Class" 
       #if 
      #for 
      if not isRun: 
       break 
     #while 
     print "END " + str(self) 
    #def 
#class 

class Run_Each(threading.Thread): 
    def __init__(self, mainWin,num ,q,daemon=True, parent=None): 
     threading.Thread.__init__(self) 
     self.mainWin = mainWin 
     self.daemon = daemon 
     self.num = num 
     self.q = q 
    #def 

    def run(self): 
     i = self.mainWin.ui.table.item(self.num,0).text() 
     self.mainWin.ui.log.append("Run_MultiplicationTable:"+i) 
     putTextEdit = eval('self.mainWin.ui.textEdit_'+ str(i)) 
     for j in range(1,10): 
      printString = str(i)+' * '+str(j)+'='+str(int(i)*j)  
      putTextEdit.append(printString) 
      #time.sleep(1) #It is job excuted time 
     #:for 
     self.mainWin.ui.table.item(self.num,1).setText('Ready') 
     self.q.put(True) 
    #def 
#class 


if __name__ == "__main__": 
    import sys 
    app = QtGui.QApplication(sys.argv) 
    MainWin = mainWindow() 
    MainWin.show() 
    sys.exit(app.exec_()) 
+0

你能提供一个最小的例子来引起错误吗?或者也许是追溯? –

+0

谢谢。第一。检查大约2-5ea的组合框。并点击运行按钮。并重复运行。 – piraji

回答

0

你不能,永远,直接修改从一个线程的GUI。这是您的分段错误的原因(并且您的连接问题可能是由于您尝试跨线程做东西)。

相反,你需要在你的主线程使用QThread(而不是Python的线程库),并从QThread发出信号到一个槽,传递任何必要的数据插槽,这样插槽可以更新GUI来自主线程。

+0

谢谢。我会尝试使用信号/插槽。 ^^ – piraji