Qt for Python でシグナル/スロットを試す

Python for Qtでシグナルとスロットの動きを試してみました。Pythonでシグナル/スロットを作成する場合も、C++版と同様に手軽に作成することができました。
2018.08.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

前回の投稿 でQt for Pythonを使って手軽にGUIアプリケーションを作れることを確認しました。今回はQtの特徴であるシグナルとスロットを作って動かしてみます。

シグナル/スロットとは

オブジェクト間でコミュニケーションするためのQtの仕組みです。例えばボタンをクリックしたらメッセージボックスを表示するという動作をさせる場合、ボタンをクリックしたという シグナル と、メッセージボックスを表示するという スロット を結びつけることで実現します。

Qtは様々なGUIコンポーネントがビルトインされていて、ボタンがクリックされた・文字を入力された・文字列が変更された、といったよく使うであろうシグナルをそのまま利用することができます。

また、シグナルはビルトインされているものだけでなく、アプリケーション固有のものを作ることもできます。今回はカスタム版のシグナルとスロットを作成してみます。

シグナルとスロットを作る

試しにスピンボックスを用意して、値が3の倍数になった場合にテキストボックスに表示するようにしてみます。

  • シグナル: 値が3の倍数になったら発火する
  • スロット: シグナルで受け取った内容をテキストボックスに表示する
import sys

from PySide2 import QtWidgets
from PySide2.QtCore import Signal, Slot


class ShowMultiplesOfThree(QtWidgets.QWidget):
    multiplesOfThree = Signal(int)  # カスタムシグナルを定義

    def __init__(self, parent=None):
        super(ShowMultiplesOfThree, self).__init__(parent)

        # カスタムシグナルとカスタムスロットを結びつけて、3の倍数になったときにテキストを更新させる
        self.multiplesOfThree.connect(self.update_text)

        # レイアウト設定、スピンボックスとテキストを用意する
        layout = QtWidgets.QVBoxLayout()

        self.sp = QtWidgets.QSpinBox()
        layout.addWidget(self.sp)
        self.sp.valueChanged.connect(self.value_changed)  # 値の変化を検知する

        self.text = QtWidgets.QPlainTextEdit()
        layout.addWidget(self.text)

        self.setLayout(layout)

    def value_changed(self):
        self.text.clear()
        if int(self.sp.value()) % 3 == 0:
            self.multiplesOfThree.emit(int(self.sp.value()))  # 3の倍数の場合はカスタムシグナル発火

    @Slot(int)
    def update_text(self, sp_value):
        self.text.appendPlainText(f'value = {sp_value}')    # カスタムシグナルを受け付けたらテキストを更新


def main():
    app = QtWidgets.QApplication(sys.argv)

    widget = ShowMultiplesOfThree()
    widget.show()

    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

実際に試してみます。

3の倍数の場合だけ数値が表示されていますね!

おわりに

今回は簡単にですがシグナルとスロットの動きを試すことができました。手軽にイベント発生・イベント処理を扱えて便利ですね。

QtはC++からしか使ったことなかったんですが、Python版も十分に安定しているようです。ちょっとしたツールを作るときに活用していきたいですね。