おことわり
この記事は次のブログからの転載です。
概要
画像のような複数のUIの操作に応じて一つのUIを更新する処理は QSignalMapper が担ってきました。
しかし Qt5 では QSignalMapper は非推奨とされ、 ラムダ式 への置き換えが推奨されます。
そこで、実際にどのように置き換えていくかをここに記録します。
従来の QSignalMapper を用いた手法
// legacy style signal mapping
mapper = new QSignalMapper(this);
QVector<QPushButton *> foobarButtons({
ui.fooButton,
ui.barButton,
ui.foobarButton,
});
for (auto const &button : foobarButtons)
{
connect(button, SIGNAL(clicked()), mapper, SLOT(map()));
mapper->setMapping(button, button->text());
}
connect(mapper, SIGNAL(mapped(QString)), this, SLOT(foobarLabelUpdate(QString)));
処理の流れは次の通りです:
- QSignalMapper を作成する。
- sender(
button
) から QSignalMapper へ connect をする。 -
QSignalMapper::map()
が実行されるとき、 QSignalMapper から送出する内容を登録する。 -
QSignalMapper::mappped()
から送出される内容を受け取る slot (foobarLabelUpdate
) へ connect する。
前提として必要なことは2つ、 QSignalMapper のインスタンス と 該当の操作に対応できるSlot そして、くじけない心です。
ラムダ式を用いた手法
// qt5 style signal mapping
QVector<QPushButton *> fizzbuzzButtons({
ui.fizzButton,
ui.buzzButton,
ui.fizzbuzzButton,
});
for (auto const &button : fizzbuzzButtons)
{
auto const &text = button->text();
connect(button, &QPushButton::clicked, [=] { ui.fizzbuzzLabel->setText(text); });
}
処理の流れは次の通りです:
- sender(
button
) からラムダ式へ connect をする。
もう少し言うと、[=]
ではじまるラムダ式なので送出していた内容を変数text
に格納するという準備をしています。
これは比較のためにQStringで揃えているだけですので、コメントで指摘いただきましたが、buttonそのものを渡すことでより簡潔に書けます。
for (auto const &button : fizzbuzzButtons)
{
connect(button, &QPushButton::clicked, [=] { ui.fizzbuzzLabel->setText(button->text()); });
}
非常にシンプルになりました。
これなら気軽に書いていけますね。
参考資料
- QSignalMapper Class | Qt Core 5.12.2
- QObject Class | Qt Core 5.12.2
- ラムダ式 - cpprefjp C++日本語リファレンス
-
GitHub - dnaga392/signalmap : 上記のコードは
mappingwidget.cpp
にあります。