使用PyQt4編寫界面后台程序的方法總結
一、怎么建立多線程
界面程序如果有稍微耗時一點的任務如果不使用多線程就會界面卡死,所以大多數情況會使用到多線程。PyQt4自己有多線程的機制,可以派生多線程類然后生成多線程實例。代碼如下:
1 form PyQt4.QtCore import *
2
3 class MyThread(QThread): 4 def __init__(self,func,args): 5 super(MyThread,self).__init__() 6 self.func = func 7 self.args = args 8
9 def run(self): 10 self.func(self,args)
在創建線程時,只要向MyThread實例傳參,參數內容為實際要調用的耗時函數及其參數就可以了,如下:
class Ui(): self.thread1 = MyThread(func,args) self.thread1.start() #此處開始自動調用線程的run函數
PS:在一個程序中只有一個主線程,在界面程序中該主線程就是界面所在的線程,其他產生的線程都是子線程;子線程創建后執行任務,當任務執行完后會自動消亡,所以可以對每個耗時的任務分別設置一個新的線程是沒有問題的
二、如何在界面中打印日志
此處我分為了兩種情況,第一種是需要使用線程的耗時任務的日志,第二種是不需要使用線程的任務的日志。
1、使用線程調用任務函數
這種情況下,在線程類中創建信號並將其作為參數傳給任務函數,在主界面類中connect,代碼如下:
1 form PyQt4.QtCore import *
2
3 class MyThread(QThread): 4 sendlog = pyqtSignal(str) 5 def __init__(self,func,args,s): 6 super(MyThread,self).__init__() 7 self.func = func 8 self.args = args 9 self.s = s 10 def run(self): 11 self.sendlog.connect(self.s) 12 self.func(self,args,self.sendlog)
在被線程調用的func中接收signal,然后有log要顯示時用signal.emit(log),其中需將log變為unicode字符否則界面顯示中文會有亂碼
其中self.s為主界面向控件輸入日志的控件,即接收信號的函數,在線程中做connect可以避免在主線程中每次創建一個新線程都需要connect一次
2、不使用線程
在任務類中建立與上面相同的信號,在主界面中進行connect。此處有一個問題需注意,如果創建信號的類不是派生類就會報錯,我是讓類隨便繼承了一個類QFile后問題就沒有了
三、關於信號的定義及引用
信號需要定義在類的初始化函數外,且為類屬性,不能是實例屬性,即定義時信號名前面沒有self
引用signal時必須用類的實例,因為用實例引用時pyqt就會自動把信號同實例綁定即產生一個綁定的信號,綁定的信號才有connect()、emit()等方法,類直接引用信號嘗試connect時,會有編譯錯誤: AttributeError:"PyQt4.QtCore.pyqtSignal" object has no attribute "connect"