簡介
PyQt API 是一組包含大量類和函數(shù)的模塊。核心模塊如下:
- QtGui:包含了窗口系統(tǒng)、事件處理(QEvent)、2D 圖像(QImage)、基本繪畫、字體(QFont)和文字類;
- QtCore:包含所有的核心非 GUI 類;
- QtWidgets:包含一系列創(chuàng)建桌面應用的 UI 元素,所有的 GUI 元素都在這個模塊中;
- QtMultimedia:包含了處理多媒體的內容和調用攝像頭 API 的類,所有的低級多媒體類倒在這個模塊;
- QtNetwork:網(wǎng)絡編程類;
- QtOpenGL:OpenGL 支持類;
- QtPositioning:包含了定位的類,可以使用衛(wèi)星、WiFi 甚至文本;
- QtWebEngine:Qt 集成了 Web 瀏覽器;
- QtSql:包含整個 SQL 處理的類;
- QtXml:包含了處理 xml 的類,提供了 SAX 和 DOM API 的工具;
- QtSvg:包含顯示 SVG 文件內容的類;
PyQt 庫的核心就是 QtGui、QtCore 和 QtWidgets 三個模塊,他們基本包含了 GUI 創(chuàng)建和邏輯處理所需的全部類,也是我們學習 PyQt 的核心。
PyQt5不兼容 PyQt4。PyQt5有一些巨大的改進:
- 重新組合模塊,一些模塊已經(jīng)被廢棄(QtScript),有些被分為兩個子模塊(QtGui, QtWebKit);
- 添加了新的模塊,比如 QtBluetooth, QtPositioning,和 Enginio;
- 廢棄了 SINGAL()和 SLOT()的調用方式,使用了新的信號和 xx 處理方式;
- 不再支持被標記為廢棄的或不建議使用的 API;
信號與槽機制
在正式介紹 PyQt 的各個控件之前,先介紹一下 Qt 框架的信號與槽機制。信號與槽(Signal/Slots)是 Qt 編程的基礎,也是 Qt 框架的一大特色。因為有了信號與槽機制的存在,在 Qt 中處理界面組件的交互操作時變得比較直觀和簡單。
信號(Signal)就是在特定情況下被發(fā)射(emit)的一種告示,例如 PushButton 按鈕最常見的信號就是鼠標點擊的時候發(fā)射的 clicked () 信號;一個 ComboBox 最常見的信號是選擇的項目發(fā)生變化的時候發(fā)射的 CurrentIndexChanged () 信號。GUI 程序設計的主要內容就是對界面上各個組件發(fā)射的特定信號進行響應,只需要知道哪一個控件在什么情況下發(fā)射了哪些信號,然后合理地去響應這些信號即可。
槽(Slot)就是對信號響應的函數(shù)。槽的本質是一個函數(shù),他可以直接被調用,這個和普通的函數(shù)沒有什么不同,槽函數(shù)與普通函數(shù)不同的一點是:槽函數(shù)可以與一個信號關聯(lián),當信號被發(fā)射的時候,關聯(lián)的槽函數(shù)會自動被執(zhí)行。Qt 的類一般都有一些內建(build-in)的槽函數(shù),例如 QWidget 有一個槽函數(shù) close(),其功能是關閉窗口,如果一個信號與之關聯(lián),當信號發(fā)射的時候就會關閉窗口。
信號與槽是一個非常復雜的機制,其底層就是 Qt 的事件機制,我將會在后面的博文中詳細說明。
QObject
當我們打開 Qt-Designer 的時候,可以看到最頂層的 QObject 屬性設置,具體如下圖所示:

QObject 是所有對象的父對象,它定義了一個 QObject 是 Qt 對象模型的核心。這個模型的中心特性是一個非常強大的對象通信機制,稱為信號和插槽。QObject 以對象樹的形式組織自身。當創(chuàng)建 QObject 并將另一個對象作為父對象時,該對象將自動將其自身添加到父對象的子對象列表中,父對象取得子對象的所有權。QObject 在 Qt 中還提供了基本的定時器支持,高級定時器功能由 QTimer 進行實現(xiàn)。
重要方法和屬性
設置控件的屬性
-
setObjectName():設置控件的唯一標識符; -
objectName():獲取控件的名稱; -
setProperty():設置控件的一個屬性; -
property():獲取控件的屬性; -
dynamicPropertyNames():動態(tài)的獲取使用setProperty()方法設置的屬性名稱。
設置父子關系
-
setParent():設置父對象。 -
parent():獲取父對象。 -
children():獲取所有的子對象。 -
findchildren():查找改對象的所有子對象(可以指定查找的對象類型,還可以指定是查找直接還是所有子對象)
進行類型判斷:
-
isWidgetType():判定是否是一個控件類型。 -
inherits():判定一個對象時候直接/間接繼承了指定的父類。
對象刪除:
-
deleteLater():向主消息隊列發(fā)送一個事件,下一次收到該事件的時候再進行清除。(刪除對象的時候會刪除任何父子關系)
定時器
-
startTimer():開啟一個定時器。 -
killTimer():刪除定時器。 -
timerEvent():定時器執(zhí)行的事件。
信號
-
ObjectNameChanged:對象名稱發(fā)生改變的時候發(fā)出此信號。 -
destory:對象銷毀的時候發(fā)出此信號。 -
blockSignals:對象臨時屏蔽一個信號。
應用場景
- 用于 QSS 的 ID 選擇器,方便統(tǒng)一設置格式;
- 控件內存管理
- 所有得到對象都可以在一個父對象中進行自我組織;
- 內存管理變得容易,當一個父對象被銷毀,它的所有子對象也都被銷毀了;
- 一個空間是否能夠作為頂級窗口存在依賴于它是否有父控件,如果沒有父控件那么它將作為頂級窗口存在;
- 簡單定時器實現(xiàn);
- 控件類型判斷;
示例
下面的示例創(chuàng)建了三個 QObject 對象,并進行了如下演示:
- 設置 objectname 屬性;
- 設置父子關系;
- 設置 property 屬性;
# 定義三個QObject對象
widget1 = QObject()
widget2 = QObject()
widget3 = QObject()
# 設置三個控件的objectname并打印
widget1.setObjectName("widget1")
widget2.setObjectName("widget2")
widget3.setObjectName("widget3")
print(widget1.objectName()) -> widget1
print(widget2.objectName()) -> widget2
print(widget3.objectName()) -> widget3
# 設置父子關系并打印
# 只能顯示直接子對象,不能顯示間接子對象
widget3.setParent(widget2)
widget2.setParent(widget1)
print(widget1.children()) -> [<PyQt5.QtCore.QObject object at 0x0000026BC638D5E0>]
print(widget2.children()) -> [<PyQt5.QtCore.QObject object at 0x0000026BC638D790>]
print(widget1.children()[0].objectName()) -> widget2
print(widget2.children()[0].objectName()) -> widget3
# 設置property并打印
# 如果沒有設置相應屬性則返回None
widget1.setProperty("value", 1)
widget2.setProperty("value", 2)
widget3.setProperty("value", 3)
print(widget1.property('value')) -> 1
print(widget2.property('value')) -> 2
print(widget3.property('value')) -> 3
print(widget1.property('path')) -> None
下面的示例演示了 QObject 提供的定時器功能,一個 QObject 對象設置定時器,當定時器設定時間截止之后會自動調用對象的timerEvent方法(事件機制的一部分),示例源碼如下:
# 定時器示例
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
# 計數(shù)器,看timerEvent的調用次數(shù)
self.counter = 0
# 設置一個1000毫秒的定時器
self.startTimer(1000, Qt.TimerType.PreciseTimer)
# 重寫timerEvent方法
def timerEvent(self, event) -> None:
self.counter += 1
print(f"timerEvent第{self.counter}次調用")
if self.counter == 5:
print("調用結束,關閉窗口")
self.close()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec())
運行結果如下:

往期回顧
文中難免會出現(xiàn)一些描述不當之處(盡管我已反復檢查多次),歡迎在留言區(qū)指正,相關的知識點也可進行分享,希望大家都能有所收獲!!