第3章 SIGNAL/SLOTを使ってみよう

3.1 SIGNAL/SLOTの基本的な使い方

Qtで最も良く使い、Qtの特徴でもある機能がシグナル/スロット(SignalandSlot)です。

シグナルは、例えばボタン(QPushButton)が押された時にはclickedという関数が呼ばれます。 このclicked関数がシグナルとなります。 そしてシグナルが発生した時にはSLOTで指定した関数が呼び出されます。 例えば、SLOTにquit関数(この関数はプログラムを終了する時に呼び出す)を指定しておけば、ボタンを押した 後、プログラムが終了します。 わかりにくいと思うので、例を挙げて説明します。

次のコードを見てください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <QApplication>
#include <QPushButton>

int main(int argc, char** argv)
{
	QApplication app(argc, argv);
	QPushButton* button = new QPushButton("Quit");
	QObject::connect(button, SIGNAL( clicked() ),
			&app, SLOT(quit()) );
	button->show();
	return app.exec();
}

このコードを実行すると、図3.1のようになります。


PIC 図 3.1: 実行結果 (on Windows)


connect関数の第一引数はシグナル(信号)が発生する部品のアドレスを渡します。 例の場合、Quitと表示されているbuttonをセットしています。 そして、第2引数でシグナルとなる関数を指定します。 関数をシグナルに設定する場合、SIGNAL()のカッコで囲った中に関数を書きます。 QPushButtonの場合、ボタンがクリックされるとclicked関数が呼び出されます。 このclicked関数がシグナルとなります

そして第3,4引数で発生したシグナルをappに結び付けています。

第3引数にはスロット側の部品のアドレスを渡します。 そして第4引数としてSLOT()のカッコで囲った中に書いた関数をスロットとなる関数と設定します。 QApplicationクラスの関数であるquit関数はプログラムを終了する時に使います。


image1 図 3.2: Signal/Slot のイメージ図


3.2 複数のSlotについて

次は図3.3の ようなウィンドウを作ります。


image2 図 3.3: 実行結果 (on Windows)


QLineEditとQLabelという部品を使い、SignalをtextChanged関数(QLineEditが編 集されたら発生)とします。 そして今回はSlotを複数設定してみましょう。

Signalが発生したら、QLabelにもQLineEditと同じ内容が表示されるようにします。 QLabelに文字をセットする場合、setText関数を使います。

また同時にWindowのタイトルもQLineEditと同じ内容を表示させてみます。 WindowのタイトルをセットするにはsetWindowTitle関数を使います。

では次のようなコードを書いてみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
#include <QLineEdit>

int main(int argc, char** argv)
{
	QApplication app(argc, argv);
	QLabel* label = new QLabel("Hello");
	QLineEdit* edit = new QLineEdit;
	QWidget* window = new QWidget;
	QHBoxLayout* layout = new QHBoxLayout;
	
	QObject::connect(edit,SIGNAL(textChanged(QString)),
			label,SLOT(setText(QString)) );
	QObject::connect(edit,SIGNAL(textChanged(QString)),
			window,SLOT(setWindowTitle(QString)) );
	
	layout->addWidget(edit);
	layout->addWidget(label);
	window->setLayout(layout);
	window->show();

	return app.exec();
}

Signal/Slot のイメージ図は図3.4となります。


image3 図 3.4: Signal/Slot のイメージ図


14,15行目ではeditのtextChanged関数とlabelのsetText関数を結び付けています。 QStringというのは、C++でいうstringと同じです。 textChanged()だけではダメです。ちゃんと引数が付いているtextChanged(QString)を呼び出さなければなりませ ん。 そして、setText関数でlabelにeditで編集された文字列をセットしています。

16,17行目も同様にsetWindowTitle関数でwindowのTitleにeditで編集された文字列 をセットしています。

3.3 Connection の解除

いままでconnect関数を使い、SignalとSlotを設定していました。 しかし、場合によってはセットしたconnectを解除したい場合があるかもしれません。 そういった場合、disconnect関数を使います。使い方はconnectとほとんど同じです。

3.1節のコードにdisconnect 関数を付け加えたものが次のコードです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <QApplication>
#include <QPushButton>

int main(int argc, char** argv)
{
	QApplication app(argc, argv);
	QPushButton* button = new QPushButton("Quit");
	QObject::connect(button, SIGNAL( clicked() ),
			&app, SLOT(quit()) );
	QObject::disconnect(button, SIGNAL( clicked() ),
			&app, SLOT(quit()) );
	button->show();
	return app.exec();
}

connectの部分がdisconnectになっただけです。 これでコネクションを解除することができます。 もちろん、このプログラムは実行してボタンを押しても何も起こりません。

3.4 Signal/Slot のまとめ

[connect 関数]

connect(sender, SIGNAL(signal), receiver, SLOT(slot) );
  • sender : 信号が発生する部品のアドレスを渡す
  • SIGNAL(signal) : signal に信号とする関数を渡す
  • receiver : 信号を受け取る部品のアドレスを渡す
  • SLOT(slot) : 信号を受け取った際に呼び出す関数を渡す