PyQt5(b)はPyQt5信号スロット機構入門します
I.はじめ信号スロット機構
図1に示すように、信号プロファイル溝
Qtは、信号スロットのコアメカニズムであるオブジェクト指向プログラミングを通信するためのPyQtは機構です。Qtの中で、QObjectをオブジェクトとPyQtは、すべてQWidgetから継承サポート信号スロット機構を制御します。信号が送信されると、スロット機能は自動的に接続が行われます。PyQt5では、信号は、溝の機能はobject.signal.connect()メソッドによって接続されています。
次のようにグルーブ信号特性は、
(1)複数の溝を信号に接続することができる
(2)別の信号の信号に接続することができる
(3)信号パラメータは、Pythonの任意のタイプとすることができる
(4)溝を聞くことができる複数の信号
(5)信号接続溝は、同期接続、または非同期接続であってもよいです。
(6)ねじ溝を横切る信号に接続されている
(7)シグナルが切断されてもよい
の調製におけるシグナルとスロットをクラスベース、スロットベースの信号、オブジェクト間のデータ伝送に関連して、最初に定義されます。イベントまたは状態の変化は、イベント信号関連付けられた溝または実行する機能をトリガ信号を送信する場合。次のように信号を模式的機構スロット:
図2に示すように、信号は、定義されました
PyQtは内蔵信号自動的pyqtSignal関数を用いて信号QObjectをオブジェクトが信号属性クラスとして定義することができるPyQt5.QtCore.pyqtSignal関数を作成し使用して定義されます。
class pyqtSignal:
def __init__(self, *types, name: str = ...) -> None: ...
パラメータタイプは信号を定義する表現型パラメータには、名前はデフォルトクラスのプロパティ名を使用して、パラメータ信号の名前を示します。
信号のみQObjectのサブクラスで定義することができるように頑丈な使用または機能pyqtSignal結合していないクラス属性複数の信号を生成します。信号が作成するクラスで定義されている必要があり、動的に追加属性クラスとして作成したクラスの後に来るではありません。pyqtSignal機能定義信号を使用する場合、信号は複数のパラメータを渡し、送信パラメータのタイプを指定することができ、パラメータ型は、文字列、日付、ブール値、数値、リスト、辞書、タプルを含む標準的なPythonのデータ型です。
from PyQt5.QtCore import pyqtSignal, QObject
class StandardItem(QObject):
# 定义信号,信号有两个参数,两个参数的类型分别为str,str,信号名称为dataChanged
data_changed = pyqtSignal(str, str, name="dataChanged")
# 更新信息,发送信号
def update(self):
self.dataChanged.emit("old status", "new status")
図3に示すように、操作信号
信号を用いて機能がスロット機能に結合することができる接続、機能は切断信号及びスロットアンバインド機能を使用することができ、機能はEMITの信号を用いて送信されてもよいです。QObject.signal.connect(self, slot, type=None, no_receiver_check=False)
接続タイプのスロットの機能、種類の信号への接続を確立します。QObject.signal.disconnect(self, slot=None)
接続溝へのOFF信号emit(self, *args)
の送信信号は、可変パラメータをARGS。
import sys
from PyQt5.QtCore import pyqtSignal, QObject, QCoreApplication
class StandardItem(QObject):
# 定义信号,信号有两个参数,两个参数的类型分别为str,str,信号名称为dataChanged
data_changed = pyqtSignal(str, str, name="dataChanged")
# 更新信息,发送信号
def update(self):
self.dataChanged.emit("old status", "new status")
# 定义槽函数
def onDataChanged(self, old, new):
print(old)
print(new)
if __name__ == "__main__":
app = QCoreApplication(sys.argv)
item = StandardItem()
item.dataChanged.connect(item.onDataChanged)
item.update()
sys.exit(app.exec_())
# OUTPUT:
# old status
# new status
第二に、信号は、溝に適用しました
1、内蔵の信号の関数溝
内蔵の信号は、信号QObjectのオブジェクトは自動的に機能が内蔵された信号に自動的に定義された関数は、QObjectを溝QObject.signal.connect機能によってオブジェクトへのQObjectのオブジェクトを接続することができるオブジェクトQObjectを内蔵スロット溝で定義されています。
図2に示すように、カスタムと内蔵の信号の関数溝
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
class MainWindow(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("MainWindow Demo")
self.resize(800, 600)
button = QPushButton("close", self)
# 连接内置信号与自定义槽
button.clicked.connect(self.onClose)
# 自定义槽函数
def onClose(self):
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
内蔵トリガボタンボタンが信号をクリックしたときに、カスタム結合溝の機能がOnCloseの実行。
3、カスタム構築された信号スロット機能
import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
class MainWindow(QWidget):
closeSignal = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("MainWindow Demo")
self.resize(800, 600)
button = QPushButton("close", self)
# 连接内置信号与自定义槽
button.clicked.connect(self.onClose)
# 连接自定义信号closeSignal与内置槽函数close
self.closeSignal.connect(self.close)
# 自定义槽函数
def onClose(self):
# 发送自定义信号
self.closeSignal.emit()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
内蔵の信号に接続することによって、カスタム関数はcloseSignalを知らせるカスタム送信し、内蔵の信号機能近いcloseSignalおよび溝接続カスタムOnCloseの画定された内部機能から溝において、溝をOnCloseのクリック。
4、カスタム関数溝付きカスタム信号
import sys
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton
class MainWindow(QWidget):
closeSignal = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("MainWindow Demo")
self.resize(800, 600)
button = QPushButton("close", self)
# 连接内置信号与自定义槽
button.clicked.connect(self.onClicked)
# 连接自定义信号closeSignal与内置槽函数close
self.closeSignal.connect(self.onClose)
# 自定义槽函数
def onClicked(self):
# 发送自定义信号
self.closeSignal.emit()
# 自定义槽函数
def onClose(self):
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
第三に、信号は、高度な溝を適用しました
図1に示すように、定義された溝からの信号
一般的に、クラス変数定義信号オブジェクトによって、__init__
以前にカスタム関数信号を定義します。
class TestObject(QObject):
# 定义无参的信号
noParametersSignal = pyqtSignal()
# 定义一个参数的信号,参数类型为int
oneParameterSignal = pyqtSignal(int)
# 定义一个参数的重载版本的信号,参数类型可以为int或str
oneParameterOverloadSignal = pyqtSignal([int], [str])
# 定义两个参数的重载版本的信号,参数类型为int,str或int,int
twoParametersOverloadSignal = pyqtSignal([int, str], [int, int])
# 定义一个list参数类型的信号
oneParameterSignalList = pyqtSignal(list)
# 定义一个dict参数类型的信号
oneParameterSignalDict = pyqtSignal(dict)
スロット・クラス定義された関数の同じ一般的なクラスで定義された方法。
class TestObject(QObject):
# 定义无参的信号
noParametersSignal = pyqtSignal()
# 定义一个参数的信号,参数类型为int
oneParameterSignal = pyqtSignal(int)
# 定义一个参数的重载版本的信号,参数类型可以为int或str
oneParameterOverloadSignal = pyqtSignal([int], [str])
# 定义两个参数的重载版本的信号,参数类型为int,str或int,int
twoParametersOverloadSignal = pyqtSignal([int, str], [int, int])
# 定义无参的槽函数
def onNoParameterSlot(self):
pass
# 定义一个参数的槽函数,参数为整型nIndex
def onOneParameterSlot(self, nIndex):
pass
# 定义两个参数的槽函数,参数为整型nIndex,字符串型sStatus
def onTwoParametersSlot(self, nIndex, sStatus):
pass
接続信号およびスロット関数法を介して接続され、信号は、同じスロット関数QObjectをオブジェクトに属することができ、又は異なるQObjectのオブジェクトであってもよいです。
test = TestObject()
test.noParametersSignal.connect(test.onNoParameterSlot)
test.oneParameterSignal.connect(test.onOneParameterSlot)
test.twoParametersOverloadSignal.connect(test.onTwoParametersSlot)
EMIT法によって送信された送信信号。
def update(self):
self.noParametersSignal.emit()
self.oneParameterSignal.emit(100)
self.oneParameterOverloadSignal("Hello, PyQt5")
self.twoParametersOverloadSignal(100, "Hello, PyQt5")
図2は、信号の通過は、カスタムパラメータを溝
パラメータの数は、Qtの放射された信号は、スロット関数の引数の数よりも大きくなければならない、PyQtは、カスタムパラメータ伝達関数パラメータは、問題の信号パラメータよりも溝用いて分割することができます。部分関数functoolsまたはカスタムパラメータを使用して、ラムダ式は、カスタムパラメータタイプは、Pythonの任意のタイプであってもよく、スロット関数に渡すことができます。
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton, QHBoxLayout
from functools import partial
class MainWindow(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
button1 = QPushButton("Button1", self)
button2 = QPushButton("Button2", self)
layout = QHBoxLayout()
layout.addWidget(button1)
layout.addWidget(button2)
self.setLayout(layout)
self.setWindowTitle("MainWindow Demo")
self.resize(800, 600)
# lambda
button1.clicked.connect(lambda: self.onButtonClicked(1))
button2.clicked.connect(lambda: self.onButtonClicked(2))
# partial
button1.clicked.connect(partial(self.onButtonClicked, 1))
button2.clicked.connect(partial(self.onButtonClicked, 2))
# 自定义槽函数
def onButtonClicked(self, n):
print("Button {0} is Clicked".format(n))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
図3に示すように、信号溝デコレータ
PyQtは信号とスロットは、以下の方法を使用して、デコレータのPythonの関数によって定義することができます。
@PyQt5.QtCore.pyqtSlot(bool)
def on_发送者对象名称_发射信号名称(self, parameter):
pass
:送信者のオブジェクト名は、信号名の後、スロット関数connectSlotsByNameの機能に接続されたオブジェクト名setObjectName QObjectをオブジェクトとして使用されるQtCore.QMetaObject.connectSlotsByName(self, QObject)
名前はQObjectに基づいて物体の一部に接続された各溝信号QObjectを子孫オブジェクトのconnectSlotsByName特定の機能を。
import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton, QHBoxLayout
class MainWindow(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
button1 = QPushButton("Button1", self)
button1.setObjectName("Button1")
button2 = QPushButton("Button2", self)
button2.setObjectName("Button2")
layout = QHBoxLayout()
layout.addWidget(button1)
layout.addWidget(button2)
self.setLayout(layout)
self.setWindowTitle("MainWindow Demo")
self.resize(800, 600)
QtCore.QMetaObject.connectSlotsByName(self)
@QtCore.pyqtSlot()
def on_Button1_clicked(self):
print("Button1 is clicked")
@QtCore.pyqtSlot()
def on_Button2_clicked(self):
print("Button2 is clicked")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
第四に、イベント処理メカニズム
差1、信号のイベントメカニズムとスロット機構
PyQtは、イベント処理のための高レベルのイベントハンドリング機構と低レベル信号のスロット機構を提供する、信号スロット機構は、機構を扱う高度なパッケージングイベントがあります。コントロールを使用する場合は、関係なく、イベント処理メカニズムの、我々は唯一のシグナルとスロットを心配する必要があります。カスタム派生コントロールのために、あなたは、デマンド制御の振る舞いに基づいて適切なイベントハンドラを再実装し、イベント処理メカニズムを考慮する必要があります。
2、イベント処理メソッド
PyQtは、すなわち、5つのイベント処理およびフィルタリング方法を提供する:
(1)再実装イベントハンドラ
一般的に使用される、そのようなイベントハンドラpaintEvent、mouseMoveEventとして、mousePressEventをmouseReleaseEventが挙げられます。
(2)QObject.eventイベント分布関数を再実装する
新しいイベントを追加するとき、我々はQObject.eventメソッドを再実装し、新しいイベントの配信経路を増やす必要があります。
(3)イベントフィルタをインストールし
ますが、オブジェクトがイベントフィルタをインストールするにQObjectたQObjectのオブジェクト、installEventFilterメソッドを呼び出した場合。すべてのイベントが最初のオブジェクトQObjectをイベント・フィルタeventFilter関数に渡される、または特定のイベントがイベントフィルタeventFilter関数で廃棄することができる修正され、他のイベントを処理するデフォルトのイベントに対して定義されたメカニズムをイベント処理から関心のあるイベントの使用メカニズム。あなたがイベントをフィルタリングする場合はより多くの、それはアプリケーションのパフォーマンスに影響しますので、すべてのイベントは、フィルタリングするメカニズムをフィルタリングイベントをQObjectをします。
(4)イベントのフィルタがインストールはQApplication
全てQObjectをイベントフィルタリングのすべてのオブジェクトにはQApplicationオブジェクトイベント・フィルタにインストールされ、他のイベントフィルタにイベントの前に送信される最初のイベントを取得する最初に送信されますQApplicationイベントフィルタ。
(5)再はQApplication方法通知
はQApplicationオブジェクトのフィルタは、はQApplicationに通知する方法を再実装する前に、イベントのイベントへの唯一の方法を捕捉するために、イベントを配布する方法を通知を使用してPyQtはします。
3、イベント処理の例
QDialog]ダイアログボックスが自動的にESCボタンを押すと、イベント処理とフィルタリングの使用はESCキー処理を押して終了します。
(1)イベントハンドラを再実装
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtCore import Qt
class Dialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
# 重新实现keyPressEvent
def keyPressEvent(self, event):
if event.key() != Qt.Key_Escape:
QDialog.keyPressEvent(self, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
dialog = Dialog()
dialog.exec_()
sys.exit(app.exec_())
(2)再実装イベント機能
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QKeyEvent
class Dialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
# 重新实现keyPressEvent
def event(self, event):
if event.type() == QKeyEvent.KeyPress and event.key() == Qt.Key_Escape:
return True
else:
return QDialog.event(self, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
dialog = Dialog()
dialog.exec_()
sys.exit(app.exec_())
(3)イベント・フィルタをインストールQObjectを
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QKeyEvent
class Dialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.installEventFilter(self)
def eventFilter(self, watched, event):
if event.type() == QKeyEvent.KeyPress and event.key() == Qt.Key_Escape:
return True
else:
return QDialog.eventFilter(self, watched, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
dialog = Dialog()
dialog.exec_()
sys.exit(app.exec_())
(4)はQApplicationイベントフィルタをインストール
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QKeyEvent
class Dialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
def eventFilter(self, watched, event):
if event.type() == QKeyEvent.KeyPress and event.key() == Qt.Key_Escape:
return True
else:
return QDialog.eventFilter(self, watched, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
dialog = Dialog()
app.installEventFilter(dialog)
dialog.exec_()
sys.exit(app.exec_())