使用Python

时间:2015-09-23 16:27:04

标签: python multithreading user-interface pyqt4

我编写了简单的python脚本,但我遇到了问题。我想运行一个没有被阻止的GUI(使用过的线程)的函数,并且该函数有多个线程。最后它产生了2种错误。第一个是

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_())

1 个答案:

答案 0 :(得分:0)

您不能直接从线程修改GUI。这是您的分段错误的原因(并且您的连接问题可能是由于您尝试跨线程执行操作)

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