0.前言
Qt是一個1991年由Qt Company開發的跨平臺C++圖形用戶界面應用程序開發框架,是目前開發桌面應用程序主流框架。PyQt5是Qt框架的Python綁定,使用SIP綁定生成器構建。注意,Qt大部分模塊爲LGPL協議,但是PyQt5爲GPL3。
開始學習前,我們先install PyQt5模塊:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple PyQt5
PyQt的文檔不是很全,可以參照PySide2的文檔:https://doc.qt.io/qtforpython/ ,PySide2是Qt官方的Python綁定版本。
1.第一個窗口
我們先實現一個簡單的窗口,再派生我們自己的窗口類。
import sys
from PyQt5.QtWidgets import QApplication,QWidget
if __name__=="__main__":
#每個Qt應用程序必須創建一個Application對象
#通過調用其exec_()運行事件循環,這樣才能週期性的處理窗口的操作、繪製等事件。
#sys.argv參數是一個列表,從命令行輸入參數。
app=QApplication(sys.argv)
#QWidget是QtWidget框架組建的基類
w=QWidget()
#設置窗口大小
w.resize(300,200)
#設置窗口標題
w.setWindowTitle("Hello World")
#顯示窗口
w.show()
#系統exit()方法確保應用程序乾淨的退出
#這裏exec_()方法有下劃線,因爲exec是一個Python關鍵字,所以用exec_()代替
sys.exit(app.exec_())
2.信號槽簡述
在Qt中,我們有一種替代回調技術的方法:我們使用信號和槽,這也是Qt的主要特性。發生特定事件時會觸發對應信號,QObject對象有一個隊列用來保存關聯的信號槽,信號觸發時會自動調用槽函數。Qt的類具有許多預定義的信號,我們在實際應用時也需要定義自己的信號,通過connect函數可以把信號關聯到別的信號或者槽函數上,槽函數在Qt5中可以是任意可調用對象。信號和插槽機制是類型安全的:信號的參數列表必須與槽函數的參數列表匹配(槽函數參數個數可以比信號參數個數更少)。詳情見文檔:https://doc.qt.io/qt-5.12/signalsandslots.html
下面通過代碼展示信號槽,我們創建兩個按鈕,一個用來關閉窗口,一個用來打印測試。
import sys
#qApp是QApplication的單例實例,如QCoreApplication::instance
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton,QVBoxLayout,qApp
#繼承QWidget,增加一個按鈕
class MyWidget(QWidget):
def __init__(self, parent=None):
#調用父類構造
super().__init__(parent=parent)
self.setWindowTitle("Hello World")
self.resize(500,400)
#創建一個佈局來放按鈕,Qt中使用parent參數來組織對象樹父子關係
vlayout=QVBoxLayout(self)
#一個按鈕
self.closeBtn=QPushButton("Close",self)
#按鈕添加到佈局
vlayout.addWidget(self.closeBtn)
#佈局設置到Widget中,此處註釋掉,已用self參數關聯
#self.setLayout(vlayout)
#按鈕點擊信號,調用app的退出函數
#槽函數可以是任意的可調用對象
self.closeBtn.clicked.connect(qApp.quit)
#另一個按鈕
self.printBtn=QPushButton("Print",self)
vlayout.addWidget(self.printBtn)
#lambda也是可調用對象,這裏我們打印選中狀態
self.printBtn.setCheckable(True)
self.printBtn.clicked.connect(lambda isCheck:print(isCheck))
if __name__=="__main__":
app=QApplication(sys.argv)
w=MyWidget()
w.show()
sys.exit(app.exec_())
3.事件簡述
在Qt中,事件是從抽象QEvent類派生的對象,它們表示發生在應用程序內部或由於應用程序需要了解的外部活動而發生的事情。事件可以由QObject子類的任何實例接收和處理,但它們與小部件尤其相關。
根據事件的創建方式和分配方式,事件可以分爲三類:
- 窗口系統會生成自發事件( Spontaneous events )。它們被放入系統隊列,並由事件循環一個接一個地處理。
- 發佈事件( Posted events )由Qt或應用程序生成。它們由Qt排隊並由事件循環處理。
- 發送事件( Sent events )是由Qt或應用程序生成的,但它們直接發送到目標對象。
當我們調用QApplication的 exec_() 函數時,應用程序進入Qt的事件循環。
Qt中的事件可以在五個不同級別上進行處理:
- 重新實現特定的事件處理程序。( 如 paint 事件的 paintEvent() )
- 重新實現 QObject 的 event() 函數。
- 在 QObject 上安裝事件過濾器。
- 在qApp上安裝事件過濾器。( qApp是QApplication的單例實例 )
- 重新實現QApplication的 notify() 函數。
詳情見文檔:https://doc.qt.io/qt-5.12/eventsandfilters.html
下面通過代碼展示事件處理程序怎麼寫,給resizeEvent改變窗口大小的處理程序加個打印語句。
import sys
from PyQt5.QtGui import QResizeEvent
from PyQt5.QtWidgets import QApplication,QWidget
#繼承QWidget,增加resize改變窗口大小的事件處理
class MyWidget(QWidget):
def __init__(self, parent=None):
#調用父類構造
super().__init__(parent=parent)
self.setWindowTitle("Hello World")
self.resize(500,400)
def resizeEvent(self,event):
#super().resizeEvent(event)
#打印尺寸
print(event.size())
if __name__=="__main__":
app=QApplication(sys.argv)
w=MyWidget()
w.show()
sys.exit(app.exec_())
4.參考
Qt信號槽文檔:https://doc.qt.io/qt-5.12/signalsandslots.html
Qt事件系統文檔:https://doc.qt.io/qt-5.12/eventsandfilters.html
Qt事件處理文檔:https://doc.qt.io/archives/qq/qq11-events.html
PyQt5文檔:https://www.riverbankcomputing.com/static/Docs/PyQt5/introduction.html
PyQt5教程:http://code.py40.com/1961.html