スロットとシグナルを調べてみました。
シグナル
オブジェクトの変更を他のオブジェクトへ伝える仕組み
スロット
シグナルを受け取って動作する関数またはメソッド
PysideのGUIアプリで使われるButtonなどのウィジェットでは、Buttonをクリックした際発生するシグナルがあらかじめ.clickedという名称で組み込まれており、スロットなる関数と結合する場合、オブジェクト名.clicked.connect(関数名(スロット)という形式になります。イベント駆動型の仕組みで他言語などでも良く見るスタイルと同じように扱うことが出来そうです。
ウィジェットなど組み込みのオブジェクトではなく、ユーザーが定義するクラスのオブジェクトでシグナルとスロットの仕組みを使い、データバインディングのデータソースとして活用することが出来るようです。
import sys
from PySide6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
from PySide6.QtCore import Signal, QObject
class DataSource(QObject):
"""データソースクラス"""
dataChanged = Signal(str) # データ変更シグナル
def __init__(self, initial_data):
super().__init__()
self._data = initial_data
@property
def data(self):
return self._data
@data.setter
def data(self, new_data):
self._data = new_data
self.dataChanged.emit(new_data) # データ変更を通知
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.data_source = DataSource("初期データ") # データソースの作成
self.button = QPushButton(self.data_source.data) # ボタンの作成と初期テキストの設定
layout = QVBoxLayout(self)
layout.addWidget(self.button)
# シグナルとスロットの接続
self.data_source.dataChanged.connect(self.update_button_text)
self.button.clicked.connect(self.change_data)
def update_button_text(self, new_text):
"""ボタンのテキストを更新するスロット"""
self.button.setText(new_text)
def change_data(self):
"""データを変更するスロット"""
if self.data_source.data == "データ1":
self.data_source.data = "データ2"
else:
self.data_source.data = "データ1"
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec())
ボタンをおすとボタンの文字列が変化します。
QObjectを継承したDataSourceクラスを作成します。
@property
でプロパティとして参照、@data.setter
でプロパティの値をセットしますが、
self.dataChanged.emit(new_data) # データ変更を通知
dataChanged = Signal(str) # データ変更シグナル
でデータ変更の通知を行っています。
# シグナルとスロットの接続
self.data_source.dataChanged.connect(self.update_button_text)
データソース⇒バインディングするボタンウィジェットのプロパティとなっています。
コメント