PyQt5入門 PythonでGUI作成 - yu00’s blog
ここではシグナルとスロットについて,
詳しい使い方を説明します.
シグナルとスロットを接続する
シグナルとスロットを接続(設定)するにはconnect()を使います.
connect(slot)
シグナルにスロットslotを接続します.
(一部引数を省略しています.すべての引数はリファレンスを参照してください)
サンプルコード
app = QApplication(sys.argv)
button = QPushButton('button')
button.clicked.connect(app.quit)
スロットを解除する
一度接続したスロットを解除するにはdisconnect()を使います.
disconnect([slot])
スロットslotを解除します.slotを省略した場合,
そのシグナルに設定されたすべてのスロットが解除されます.
サンプルコード
app = QApplication(sys.argv)
button = QPushButton('button')
button.clicked.connect(app.quit)
button.clicked.disconnect(app.quit)
一つのシグナルに複数のスロットを接続する
一つのシグナルに複数のスロットを設定することができます.
スロットは接続された順に実行されます.
サンプルコード
一つのボタンのシグナルに二つのラベルのスロットを設定しています.
button = QPushButton('button')
label1 = QLabel('label1')
label2 = QLabel('label2')
button.clicked.connect(label1.clear)
button.clicked.connect(label2.clear)
複数のシグナルに一つのスロットを接続する
複数のシグナルに同じスロットを接続することができます.
サンプルコード
二つのボタンのシグナルに一つのラベルのスロットを設定しています.
button1 = QPushButton('button1')
button2 = QPushButton('button2')
label = QLabel('label')
button1.clicked.connect(label.clear)
button2.clicked.connect(label.clear)
シグナルの引数をスロットに渡す
シグナルとスロットの関数に引数があった場合,
シグナルの引数と同じ値がスロットの引数に渡されます.
引数はいくつあってもよいですが,
引数の型は同じである必要があります.
サンプルコード
シグナルにQLineEdit.textChanged(str),
スロットにQLabel.setText(str)を使っています.
lineEdit = QLineEdit()
label = QLabel('label')
lineEdit.textChanged.connect(label.setText)
実行例
編集エリアに文字を入力すると同じ文字が下のラベルに
表示されます.
シグナルにオーバーロードがある場合は
connectのときどれを使うかを指定します.
例えばsignal(int, int)とsignal(QString)という
2つのオーバーロードがあるシグナルがあるとします.
この場合は次のように使い分けます.
signal[int, int].connect(slot1)
signal['QString'].connect(slot2)
このようにC++に対応するPythonの型かC++の型を文字で
指定します.
シグナルを自作する
シグナルを自作するにはpyqtSignal()とemit()を使います.
シグナルを作成するにはQObjectを継承したクラスのクラス変数として
pyqtSignal()を定義します.
そして,emit()を呼ぶことでシグナルが発行されます.
pyqtSignal([types])
シグナルを作成します.
types:
シグナルの引数の型です.型はC++に対応するPythonの型,または
C++の型名の文字で指定します.オーバーロードがある場合,
それぞれの型はリストで指定します.
(一部引数を省略しています)
次はpySignal()を使ってシグナルを作成する例です.
from PyQt5.QtCore import QObject, pyqtSignal
class MyObject(QObject):
signal1 = pyqtSignal()
signal2 = pyqtSignal(int, int)
signal3 = pyqtSignal([int, str], ['QString'])
emit(*args)
シグナルを発行します.
args:スロットに渡される引数です.
サンプルコード
例として,Aボタンが押されたときに
シグナルを発行するウィジェットを作り,
Aボタンが押されたときに閉じるようにしてみます.
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt, pyqtSignal
class MyWidget(QWidget):
pressedA = pyqtSignal()
def __init__(self):
super().__init__()
self.init_ui()
self.show()
def init_ui(self):
self.pressedA.connect(self.close)
def keyPressEvent(self, e):
if e.key() == Qt.Key_A:
self.pressedA.emit()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWidget()
sys.exit(app.exec_())
スロットを自作する
Pythonの関数をスロットとして使用することができます.
サンプルコード
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
self.show()
def init_ui(self):
self.button = QPushButton('button', self)
self.button.clicked.connect(self.button_clicked)
def button_clicked(self):
""" 自作のスロット """
print('button clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWidget()
sys.exit(app.exec_())
シグナルを発行したオブジェクトを取得する
複数のシグナルに1つのスロットが設定されていたとき,
QObject.sender()を使うことでシグナルを発行した
オブジェクトを取得できます.
サンプルコード
2つのボタンどちらが押されたかを表示するプログラムを書いてみます.
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
self.show()
def init_ui(self):
self.button1 = QPushButton('1')
self.button2 = QPushButton('2')
layout = QVBoxLayout(self)
layout.addWidget(self.button1)
layout.addWidget(self.button2)
self.button1.clicked.connect(self.button_clicked)
self.button2.clicked.connect(self.button_clicked)
def button_clicked(self):
button = self.sender()
if button is self.button1:
print('button 1')
elif button is self.button2:
print('button 2')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWidget()
sys.exit(app.exec_())