PyQt5(5)信号およびスロットメカニズム

信号とスロットのメカニズムはQTのコアメカニズムです。QTプログラミングに習熟するには、信号とスロットを理解している必要があります。シグナルとスロットは、オブジェクト間の通信に使用される高レベルのインターフェースであり、QTのコア機能であり、QTと他のツールキットの重要な違いです。

シグナルとスロットは、オブジェクト間でデータを渡すために使用されるメソッドです。特定のイベントが発生すると、シグナルが発行され、スロット呼び出しが対応するシグナルに応答するために使用されます。Qtのオブジェクトにはすでに多くの事前定義されたシグナルが含まれており(基本コンポーネントには独自の事前定義されたシグナルがあります)、使用シナリオに応じて新しいシグナルを追加できます。同様に、多くの事前定義されたスロット機能がすでにQtオブジェクトに含まれていますが、使用シナリオに応じて新しいスロット機能を追加することもできます。

1.コンセプト紹介

qwidgetを継承するすべてのコントロールは、シグナルおよびスロットメカニズムをサポートします。

信号:信号が変化したときに外界に送信されるメッセージ。

信号が発信されると、関連するスロット機能がすぐに実行されます。オブジェクトは信号の送信のみを担当し、信号を送信するオブジェクトは、どのオブジェクトが信号を受信して​​いるかを認識しません。これにより、オブジェクト間の結合度が低くなります。
複数のスロット機能に関連する信号がある場合、信号が発信されると、これらのスロットの実行順序はランダムで不確定になります。

スロット:何らかのアクションを実行する関数またはメソッド。

スロットに接続された信号が発信されると、スロットが呼び出されます。スロットは、それ自体に信号が接続されているかどうかを知りません。

信号とスロットのメカニズム:主に2つのタイプに分けられます

手動操作:信号接続スロット

自動運転:信号が発信されると、連続するスロット機能が自動的に実行されます

信号接続

QObjectオブジェクトのconnect関数を呼び出して、オブジェクトの信号を別のオブジェクトのslot関数に関連付けることにより、送信者が信号を送信すると、受信者のslot関数が呼び出されます。関数は次のように定義されています。

object.信号.connet(槽函数)

切断機能は、スロットに関連付けられたままにする必要がない場合に信号を切断するために使用できます。これは次のように定義されます。

disconnect(槽函数)

信号とスロットの機能:

1.信号は複数のスロットに接続できます。信号が送信されると、スロット関数が呼び出されますが、呼び出しの順序はランダムで不確実です。

2.同じスロットに複数の信号を接続することができます。いずれかの信号が発信され、スロット機能が実行されます。

3.シグナルのパラメーターは、list、dict、およびpythonに固有の他のタイプなどの任意のPythonタイプにすることができます。信号をカスタマイズするときの例を示します。

4.特定の信号を切断するなど、信号とスロット間の接続を削除できます。

5.信号を別の信号に関連付けることができます。最初の信号が送信された後、2番目の信号が同時に送信されます。たとえば、システムをシャットダウンするための信号が発行された後、データを保存するための信号が同時に発行されます。

2.コードサンプル

全体的なコードは次のとおりです。

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,QGridLayout,QLabel,QHBoxLayout, QGroupBox,
    QVBoxLayout, QApplication,QProgressBar,QPushButton,QMessageBox)


class SignalSlot(QWidget):

    def __init__(self):
        super(SignalSlot,self).__init__()      
        self.initUI()


    def initUI(self):

        self.controlsGroup = QGroupBox("运行样本")
        self.lcdNumber = QLCDNumber(self)
        self.slider = QSlider(Qt.Horizontal, self)
        self.pBar = QProgressBar(self)
        vbox = QVBoxLayout()
        vbox.addWidget(self.pBar)
        vbox.addWidget(self.lcdNumber)
        vbox.addWidget(self.slider)
        self.controlsGroup.setLayout(vbox)

        controlsLayout = QGridLayout()
        self.label1 = QLabel("保存状态:")
        self.saveLabel = QLabel()
        self.label2 = QLabel("运行状态:")
        self.runLabel = QLabel()
        self.buttonSave = QPushButton("保存")
        self.buttonRun = QPushButton("运行")
        self.buttonStop = QPushButton("停止")
        self.buttonDisconnect = QPushButton("解除关联")
        self.buttonConnect = QPushButton("绑定关联")

        controlsLayout.addWidget(self.label1,0,0)
        controlsLayout.addWidget(self.saveLabel,0,1)
        controlsLayout.addWidget(self.label2,1,0)
        controlsLayout.addWidget(self.runLabel,1,1)
        controlsLayout.addWidget(self.buttonSave,2,0)
        controlsLayout.addWidget(self.buttonRun,2,1)
        controlsLayout.addWidget(self.buttonStop,2,2)
        controlsLayout.addWidget(self.buttonDisconnect,3,0)
        controlsLayout.addWidget(self.buttonConnect,3,1)

        layout = QHBoxLayout()
        layout.addWidget(self.controlsGroup)
        layout.addLayout(controlsLayout)
        self.setLayout(layout)

        self.buttonRun.clicked.connect(self.buttonSave.clicked)
        self.slider.valueChanged.connect(self.pBar.setValue)
        self.slider.valueChanged.connect(self.lcdNumber.display)
        self.buttonSave.clicked.connect(self.showMessage)
        self.buttonRun.clicked.connect(self.showMessage)
        self.buttonDisconnect.clicked.connect(self.unbindConnection)
        self.buttonConnect.clicked.connect(self.bindConnection)
        self.buttonStop.clicked.connect(self.stop)

        self.setGeometry(300, 500, 500, 180)
        self.setWindowTitle('信号和槽')

    def showMessage(self):
        if self.sender().text() == "保存":
            self.saveLabel.setText("Saved")
        elif self.sender().text() == "运行":
            self.saveLabel.setText("Saved")
            self.runLabel.setText("Running")

    def unbindConnection(self):
        self.slider.valueChanged.disconnect()
    def bindConnection(self):
        self.slider.valueChanged.connect(self.pBar.setValue)
        self.slider.valueChanged.connect(self.lcdNumber.display)
    def stop(self):
        self.saveLabel.setText("")
        self.runLabel.setText("")

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = SignalSlot()
    ex.show()
    sys.exit(app.exec_())

コントロールの説明:

コントロールタイプ コントロール名 効果
コントロールグループ QGroupBox グループボックスの構築をサポートします。グループボックスは、通常、境界線とタイトルバーがあり、さまざまなウィジェットを配置できるコンテナウィジェットとして機能します。
lcdNumber QLCDNumber LCDのような効果で数値を表示するために使用されます。
スライダー QSlider 垂直または水平スライダーを提供します。スライダーは境界値を制御するための一般的なコントロールであり、ユーザーがスライダーを水平または垂直方向に特定の範囲で移動できるようにし、スライダーの位置を整数値に変換します。法的範囲
pBar QProgressBar 水平または垂直のプログレスバーを提供します
label1 QLabel
  • プレースホルダー
  • テキストを表示
  • 画像を表示
  • gifアニメーションを配置する
  • ハイパーリンク
  • キューマーク
ボタン保存 QPushButton 一般的に使用されるボタンコントロール

インターフェイスの説明: 

プログラムサンプル実行のインターフェイスロジックは、最初に実行中のプログラムサンプルの数を設定し、次に実行中のロジック状態を最初に保存します。スライダーをスライドさせてプログレスバーとLCDの表示データを変更します。「保存」ボタンは実行中のサンプルを保存します。「実行」ボタンはプログラムサンプルを実行します。プログレスバーとLCDの表示を変更します。

self.controlsGroup = QGroupBox("运行样本")
self.lcdNumber = QLCDNumber(self)
self.slider = QSlider(Qt.Horizontal, self)
self.pBar = QProgressBar(self)
vbox = QVBoxLayout()
vbox.addWidget(self.pBar)
vbox.addWidget(self.lcdNumber)
vbox.addWidget(self.slider)
self.controlsGroup.setLayout(vbox)

QGroupBoxをインスタンス化し、QProgressBar、QLCDNumber、およびQSliderコントロールを追加します。

controlsLayout = QGridLayout()
self.label1 = QLabel("保存状态:")
self.saveLabel = QLabel()
self.label2 = QLabel("运行状态:")
self.runLabel = QLabel()
self.buttonSave = QPushButton("保存")
self.buttonRun = QPushButton("运行")
self.buttonStop = QPushButton("停止")
self.buttonDisconnect = QPushButton("解除关联")
self.buttonConnect = QPushButton("绑定关联")

controlsLayout.addWidget(self.label1,0,0)
controlsLayout.addWidget(self.saveLabel,0,1)
controlsLayout.addWidget(self.label2,1,0)
controlsLayout.addWidget(self.runLabel,1,1)
controlsLayout.addWidget(self.buttonSave,2,0)
controlsLayout.addWidget(self.buttonRun,2,1)
controlsLayout.addWidget(self.buttonStop,2,2)
controlsLayout.addWidget(self.buttonDisconnect,3,0)
controlsLayout.addWidget(self.buttonConnect,3,1)

QGridLayout()を使用してラベルとボタンを追加します。

layout = QHBoxLayout()
layout.addWidget(self.controlsGroup)
layout.addLayout(controlsLayout)
self.setLayout(layout)

 最後に、左右のインターフェイスがQHBoxLayoutを介してマージされ、最終的なインターフェイスが形成されます。

信号とスロットの説明:

信号とスロットがバインドされています。
1.信号は複数のスロットをバインドします。

self.slider.valueChanged.connect(self.pBar.setValue)

self.slider.valueChanged.connect(self.lcdNumber.display)

スライダーコントロールのvalueChangedシグナルは、QProgressBarのsetValue()およびQLCDNumberのdisplay()スロット関数にもバインドされます。valueChangedシグナルがトリガーされると、これら2つのスロット関数が呼び出されます。

2.複数の信号がスロットにバインドされます。

self.buttonSave.clicked.connect(self.showMessage)
self.buttonRun.clicked.connect(self.showMessage)

2つのオブジェクトbuttonSaveとbuttonRunのクリックされたシグナルは、スロット関数showMessage()にバインドされます。どの信号がトリガーされても、スロット関数showMessage()が呼び出され、表示されるさまざまなコンテンツが関数self.sender()。text()に従って判断されます。

3.信号とスロットの接続を削除できます。

self.buttonDisconnect.clicked.connect(self.unbindConnection)

buttonDisconnectシグナルがトリガーされると、disconnect()メソッドが関連するスロット関数unbindConnection()で次のように実行されます。

def unbindConnection(self):
        self.slider.valueChanged.disconnect()

disconnect()を実行するときに、self.slider.valueChanged.disconnect(self.pBar.setValue)などの特定のスロットとの関連付けを解除するように指定できます。このとき、QProgressBarのsetValue()との関連付けを解除します。指定されていない場合は、すべてこの信号に関連付けられているスロットは解放されます。

4.信号と信号の相関関係:

self.buttonRun.clicked.connect(self.buttonSave.clicked)

サンプルの説明で説明したように、サンプルは実行前に保存する必要があるため、実行時に保存操作が確実に実行されるように、buttonRun.clickedシグナルはbuttonSave.clickedシグナルに関連付けられています。

この例では、「保存」(buttonSave)を実行しない場合、「実行」(buttonRun)を実行します。このとき、2つのオブジェクトのクリック信号はすでに関連付けられているため、buttonSaveのクリックも実行されます。

最終結果:

この記事は「ScratchからPyQt5を学ぶ」の第5部です。皆さんが一緒にサポートし、学ぶことができることを願っています。


参照する:

Pyqt5シリーズ(7)-信号とスロットのメカニズム-太陽を追いかける風-CSDNブログ-pyqt5信号とスロット

おすすめ

転載: blog.csdn.net/kobepaul123/article/details/122934359