- 指數
- 班級 |
- 模塊 |
- PyQt v5.14.0參考指南 »
支持信號和插槽
Qt的主要特徵之一是它使用信號和插槽在對象之間進行通信。它們的使用鼓勵了可重用組件的開發。
當潛在的事情發生時,發出信號。插槽是可調用的Python。如果將信號連接到插槽,則在發出信號時將調用該插槽。如果沒有連接信號,則什麼也不會發生。發出信號的代碼(或組件)不知道或不在乎是否正在使用該信號。
信號/插槽機制具有以下功能。
-
信號可能連接到許多插槽。
-
一個信號也可以連接到另一個信號。
-
信號參數可以是任何Python類型。
-
插槽可以連接到許多信號。
-
連接可以是直接的(即同步)或排隊的(即異步)。
-
可以跨線程進行連接。
-
信號可能斷開。
粘結和粘結信號
信號(特別是未綁定的信號)是類屬性。當信號被引用爲該類實例的屬性時,PyQt5會自動將該實例綁定到該信號,以創建綁定信號。這與Python本身用於從類函數創建綁定方法的機制相同。
一個綁定信號具有connect()
,disconnect()
和emit()
實現相關聯的功能的方法。它還具有一個signal
屬性,它是Qt SIGNAL()
宏將返回的信號的簽名。
信號可能過載,即。具有特定名稱的信號可能支持多個簽名。可以用簽名對信號進行索引,以選擇所需的信號。簽名是一系列類型。類型可以是Python類型對象,也可以是C ++類型名稱的字符串。C ++類型的名稱會自動進行規範化,例如,QVariant
可以使用它來代替non-normalized 。const QVariant &
如果信號過載,那麼它將有一個默認值,如果沒有給出索引,它將被使用。
發出信號時,如有可能,所有參數都將轉換爲C ++類型。如果參數沒有相應的C ++類型,則將其包裝在特殊的C ++類型中,該參數允許在Qt的元類型系統中傳遞該參數,同時確保正確維護其引用計數。
使用pyqtSignal定義新信號
PyQt5自動爲所有Qt的內置信號定義信號。可以使用pyqtSignal工廠將新信號定義爲類屬性 。
PyQt5.QtCore.
pyqtSignal
(類型[,名稱[,版本= 0 [,參數= [] ] ] ] )
創建一個或多個重載的未綁定信號作爲類屬性。
參量
-
類型 –定義信號的C ++簽名的類型。每個類型可以是Python類型對象,也可以是C ++類型名稱的字符串。或者,每個參數可以是類型參數的序列。在這種情況下,每個序列定義了不同信號過載的特徵。默認爲第一次過載。
-
名稱 -信號名稱。如果省略,則使用class屬性的名稱。這隻能作爲關鍵字參數給出。
-
修訂版 –導出到QML的信號的修訂版。這隻能作爲關鍵字參數給出。
-
arguments –導出到QML的信號參數名稱的順序。這隻能作爲關鍵字參數給出。
返回類型
未綁定的信號
以下示例顯示了許多新信號的定義:
from PyQt5.QtCore import QObject, pyqtSignal
class Foo(QObject):
# This defines a signal called 'closed' that takes no arguments.
closed = pyqtSignal()
# This defines a signal called 'rangeChanged' that takes two
# integer arguments.
range_changed = pyqtSignal(int, int, name='rangeChanged')
# This defines a signal called 'valueChanged' that has two overloads,
# one that takes an integer argument and one that takes a QString
# argument. Note that because we use a string to specify the type of
# the QString argument then this code will run under Python v2 and v3.
valueChanged = pyqtSignal([int], ['QString'])
新信號只能在QObject的子類中定義 。它們必須是類定義的一部分,並且在定義類後不能動態添加爲類屬性。
以這種方式定義的新信號將自動添加到類的 QMetaObject中。這意味着它們將出現在Qt Designer中,並且可以使用QMetaObject API 進行內省 。
當參數的Python類型沒有對應的C ++類型時,應謹慎使用重載信號。PyQt5使用相同的內部C ++類來表示此類對象,因此可能會產生帶有不同Python簽名的重載信號,這些信號用相同的C ++簽名實現會產生意外結果。以下是一個示例:
class Foo(QObject):
# This will cause problems because each has the same C++ signature.
valueChanged = pyqtSignal([dict], [list])
連接,斷開連接和發射信號
使用connect()
綁定信號的方法將信號連接到插槽。
connect
(時隙[,類型= PyQt5.QtCore.Qt.AutoConnection [,no_receiver_check =假] ] ) →PyQt5.QtCore.QMetaObject.Connection
將信號連接到插槽。如果連接失敗,將引發異常。
參量
-
slot –要連接的插槽,可以是Python可調用的信號,也可以是另一個綁定的信號。
-
type –進行連接的類型。
-
no_receiver_check –禁止檢查基礎C ++接收器實例是否仍然存在,並始終傳遞信號。
退貨
可以傳遞給的Connection對象disconnect()
。這是斷開與lambda函數的連接的唯一方法。
使用disconnect()
綁定信號的方法將信號從插槽斷開。
disconnect
([ 插槽] )
從信號上斷開一個或多個插槽。如果插槽未連接到信號或信號根本沒有連接,則會引發異常。
參量
slot –要從中斷開連接的可選插槽,它是由Python可調用的返回的 Connection對象 connect()
或另一個綁定的信號。如果省略,則所有與信號連接的插槽都將斷開。
使用emit()
綁定信號的方法發出信號。
emit
(* args )
發出信號。
參量
args –傳遞給任何連接的插槽的可選參數序列。
以下代碼演示了不帶參數的信號的定義,連接和發射:
from PyQt5.QtCore import QObject, pyqtSignal
class Foo(QObject):
# Define a new signal called 'trigger' that has no arguments.
trigger = pyqtSignal()
def connect_and_emit_trigger(self):
# Connect the trigger signal to a slot.
self.trigger.connect(self.handle_trigger)
# Emit the signal.
self.trigger.emit()
def handle_trigger(self):
# Show that the slot has been called.
print "trigger signal received"
以下代碼演示了過載信號的連接:
from PyQt5.QtWidgets import QComboBox
class Bar(QComboBox):
def connect_activated(self):
# The PyQt5 documentation will define what the default overload is.
# In this case it is the overload with the single integer argument.
self.activated.connect(self.handle_int)
# For non-default overloads we have to specify which we want to
# connect. In this case the one with the single string argument.
# (Note that we could also explicitly specify the default if we
# wanted to.)
self.activated[str].connect(self.handle_string)
def handle_int(self, index):
print "activated signal passed integer", index
def handle_string(self, text):
print "activated signal passed QString", text
使用關鍵字參數連接信號
創建對象時或通過使用pyqtConfigure()
方法,還可以通過傳遞一個插槽作爲對應於信號名稱的關鍵字參數來連接信號 。例如,以下三個片段是等效的:
act = QAction("Action", self)
act.triggered.connect(self.on_triggered)
act = QAction("Action", self, triggered=self.on_triggered)
act = QAction("Action", self)
act.pyqtConfigure(triggered=self.on_triggered)
所述pyqtSlot()裝飾
儘管PyQt5允許在連接信號時將任何可調用的Python用作插槽,但有時有必要將Python方法顯式標記爲Qt插槽併爲其提供C ++簽名。PyQt5提供了 pyqtSlot()函數裝飾器來執行此操作。
PyQt5.QtCore.
pyqtSlot
(類型[,名稱[,結果[,版本= 0 ] ] ] )
裝飾Python方法以創建Qt插槽。
參量
-
類型 –定義插槽C ++簽名的類型。每個類型可以是Python類型對象,也可以是C ++類型名稱的字符串。
-
name – C ++將看到的插槽名稱。如果省略,將使用要修飾的Python方法的名稱。這隻能作爲關鍵字參數給出。
-
修訂版 –導出到QML的插槽的修訂版。這隻能作爲關鍵字參數給出。
-
result – 結果的類型,可以是Python類型的對象或指定C ++類型的字符串。這隻能作爲關鍵字參數給出。
將信號連接到經過修飾的Python方法還具有減少使用的內存量的優點,並且速度稍快。
例如:
from PyQt5.QtCore import QObject, pyqtSlot
class Foo(QObject):
@pyqtSlot()
def foo(self):
""" C++: void foo() """
@pyqtSlot(int, str)
def foo(self, arg1, arg2):
""" C++: void foo(int, QString) """
@pyqtSlot(int, name='bar')
def foo(self, arg1):
""" C++: void bar(int) """
@pyqtSlot(int, result=int)
def foo(self, arg1):
""" C++: int foo(int) """
@pyqtSlot(int, QObject)
def foo(self, arg1):
""" C++: int foo(int, QObject *) """
也可以鏈接裝飾器,以便使用不同的簽名多次定義Python方法。例如:
from PyQt5.QtCore import QObject, pyqtSlot
class Foo(QObject):
@pyqtSlot(int)
@pyqtSlot('QString')
def valueChanged(self, value):
""" Two slots will be defined in the QMetaObject. """
該PyQt_PyObject
信號參數類型
通過PyQt_PyObject
將簽名指定爲參數的類型,可以將任何Python對象作爲信號參數傳遞 。例如:
finished = pyqtSignal('PyQt_PyObject')
通常將其用於傳遞不知道實際Python類型的對象。例如,它也可以用於傳遞整數,這樣就不需要從Python對象正常轉換爲C ++整數再返回。
被傳遞對象的引用計數將自動維護。finished.emit()
即使對連接進行排隊,也不需要信號的發射器在調用之後保留對對象的引用。
通過名稱連接插槽
PyQt5支持pyuic5生成的Python代碼connectSlotsByName()
最常用的功能,以自動將信號連接到符合簡單命名約定的插槽。但是,在類重載Qt信號的情況下(即,具有相同名稱但具有不同參數的Qt信號),PyQt5需要附加信息才能自動連接正確的信號。
例如,QSpinBox類具有以下信號:
void valueChanged(int i);
void valueChanged(const QString &text);
當旋轉框的值更改時,將同時發出這兩個信號。如果您實現了一個名爲的插槽on_spinbox_valueChanged
(假定您爲QSpinBox實例指定了名稱spinbox
),則它將連接到信號的兩種變化形式。因此,當用戶更改值時,您的廣告位將被調用兩次-一次使用整數參數,一次使用字符串參數。
所述pyqtSlot()裝飾可被用於指定哪一個信號應連接到所述槽。
例如,如果您只對信號的整數變量感興趣,那麼您的插槽定義將如下所示:
@pyqtSlot(int)
def on_spinbox_valueChanged(self, i):
# i will be an integer.
pass
如果您想使用兩種不同的Python方法來處理信號的兩種變體,則插槽定義可能如下所示:
@pyqtSlot(int, name='on_spinbox_valueChanged')
def spinbox_int_value(self, i):
# i will be an integer.
pass
@pyqtSlot(str, name='on_spinbox_valueChanged')
def spinbox_qstring_value(self, s):
# s will be a Python string object (or a QString if they are enabled).
pass
- 指數
- 班級 |
- 模塊 |
- PyQt v5.14.0參考指南 »