PyQt5訊號、定時器及多線程

來源:互聯網
上載者:User

標籤:_for   hid   其它   idg   trigger   網路   計時器   參數   setup   

訊號

  訊號是用於介面自動變化的一個工具,原理是訊號綁定了一個函數,當訊號被觸發時函數即被調用

舉個例子

from PyQt5 import QtWidgets,QtCorefrom untitled import Ui_Formimport  time  class MyWindow(QtWidgets.QWidget,Ui_Form):    _signal=QtCore.pyqtSignal(str) #定義訊號,定義參數為str類型    def __init__(self):          super(MyWindow,self).__init__()        self.setupUi(self)        self.myButton.clicked.connect(self.myPrint)# 按下按鈕執行myPrint        self._signal.connect(self.mySignal) #將訊號串連到函數mySignal     def myPrint(self):        self.tb.setText("")        self.tb.append("正在列印,請稍候")        self._signal.emit("列印結束了嗎")# 訊號被觸發    def mySignal(self,string):        print(string)        self.tb.append("列印結束") if __name__=="__main__":      # 以下代碼作用為展現ui介面    import sys        app=QtWidgets.QApplication(sys.argv)      myshow=MyWindow()    myshow.show()      sys.exit(app.exec_())  

 

定時器

  定時器的作用是讓某個函數定時的啟動,原理是建立一個QTimer對象,將其timeout訊號串連到相應的槽(綁定函數名),並調用start(),定時器會以恒定的間隔發出timeout訊號,直到調用stop()。

舉個例子:秒錶功能(每隔一秒重新整理介面,直到按下停止按鈕)

from PyQt5.QtWidgets import *from PyQt5.QtCore import *import sysfrom datetime import datetime class WinTimer(QWidget):    def __init__(self,parent=None):        super(WinTimer,self).__init__(parent)         ###介面顯示        self.label_start=QLabel("開始時間:")        self.label_curr=QLabel("目前時間:")        self.label_total=QLabel("時間總計:")        self.startBtn=QPushButton("開始")        self.endBtn=QPushButton("停止")        self.endBtn.setEnabled(False)         ##時間變數        self.start_time=QDateTime.currentDateTime()        self.stop_time = QDateTime.currentDateTime()         ###定時器        self.timer=QTimer()        self.timer.timeout.connect(self.currTime)         layout=QGridLayout()        layout.addWidget(self.label_start,0,0,1,2)        layout.addWidget(self.label_curr, 1,0,1,2)        layout.addWidget(self.label_total, 2,0,1,2)        layout.addWidget(self.startBtn, 3, 0)        layout.addWidget(self.endBtn, 3, 1)        self.setLayout(layout)         self.startBtn.clicked.connect(self.startTimer)        self.endBtn.clicked.connect(self.endTimer)         self.setWindowTitle("QTimer")        self.resize(250,100)     def currTime(self):        self.stop_time=QDateTime.currentDateTime()        str_time = self.stop_time.toString("yyyy-MM-dd hh:mm:ss dddd")        self.label_curr.setText("目前時間:"+str_time)                str_start = self.start_time.toString("yyyy-MM-dd hh:mm:ss")        str_curr = self.stop_time.toString("yyyy-MM-dd hh:mm:ss")        startTime = datetime.strptime(str_start, "%Y-%m-%d %H:%M:%S")        endTime = datetime.strptime(str_curr, "%Y-%m-%d %H:%M:%S")        seconds = (endTime - startTime).seconds        self.label_total.setText("時間總計:" + str(seconds)+"s")     def startTimer(self):        self.start_time = QDateTime.currentDateTime()        str_time = self.start_time.toString("yyyy-MM-dd hh:mm:ss dddd")        self.label_start.setText("開始時間:" + str_time)        self.timer.start(1000)        self.startBtn.setEnabled(False)        self.endBtn.setEnabled(True)     def endTimer(self):        self.timer.stop()        self.startBtn.setEnabled(True)        self.endBtn.setEnabled(False) if __name__=="__main__":    app=QApplication(sys.argv)    form=WinTimer()    form.show()
View Code

 

多線程

  假設我們的主介面有一個用於顯示時間的 LCD 數字面板和一個用於啟動任務的按鈕。程式的目的是使用者點擊按鈕,開始一個非常耗時的運算(程式中我們以一個 2000000000 次的迴圈來替代這個非常耗時的工作,在真實的程式中,這可能是一個網路訪問,可能是需要複製一個很大的檔案或者其它任務),同時 LCD 開始顯示逝去的毫秒數。毫秒數通過一個計時器QTimer進行更新。計算完成後,計時器停止。這是一個很簡單的應用,也看不出有任何問題。但是當我們開始運行程式時,問題就來了:點擊按鈕之後,程式介面直接停止回應,直到迴圈結束才開始重新更新,於是計時器使用顯示0。

  這是因為 Qt 中所有介面都是在 UI 線程中(也被稱為主線程,就是執行了QApplication::exec()的線程),在這個線程中執行耗時的操作(比如那個迴圈),就會阻塞 UI 線程,從而讓介面停止回應。介面停止回應,使用者體驗自然不好,不過更嚴重的是,有些視窗管理程式會檢測到你的程式已經失去響應,可能會建議使用者強制停止程式,這樣一來程式可能就此終止,任務再也無法完成。所以,為了避免這一問題,我們要使用 QThread 開啟一個新的線程:

# coding=utf-8 __author__ = ‘a359680405‘ from PyQt5.QtCore import *from PyQt5.QtGui import *from PyQt5.QtWidgets import * global sec sec=0class WorkThread(QThread):   trigger = pyqtSignal()   def __int__(self):     super(WorkThread,self).__init__()     def run(self):     for i in range(203300030):       pass    self.trigger.emit()     #迴圈完畢後發出訊號   def countTime():   global sec   sec+=1  lcdNumber.display(sec)     #LED顯示數字+1   def work():   timer.start(1000)        #計時器每秒計數   workThread.start()       #計時開始   workThread.trigger.connect(timeStop)  #當獲得迴圈完畢的訊號時,停止計數   def timeStop():   timer.stop()   print("運行結束用時",lcdNumber.value())   global sec   sec=0 app=QApplication([]) top=QWidget() layout=QVBoxLayout(top)       #垂直布局類QVBoxLayout; lcdNumber=QLCDNumber()       #加個顯示屏 layout.addWidget(lcdNumber) button=QPushButton("測試") layout.addWidget(button)  timer=QTimer() workThread=WorkThread() button.clicked.connect(work) timer.timeout.connect(countTime)   #每次計時結束,觸發setTime  top.show() app.exec()
View Code

 

  上述代碼增加了一個WorkerThread類。WorkerThread繼承自QThread類,重寫了其run()函數。可以認為,run()函數就是新的線程需要執行的代碼。在這裡就是要執行這個迴圈,然後發出計算完成的訊號。而在按鈕點擊的槽函數中,使用work()中的workThread.start()函數啟動一個線程(注意,這裡不是run()函數)。再次運行程式,你會發現現在介面已經不會被阻塞了。

 

 

 

      

 

PyQt5訊號、定時器及多線程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.