Qtでシグナルをブロックする方法


はじめに

「QSpinBox の valueChanged シグナルと任意のスロットを接続して処理していたけど、このプッシュボタンでスピンボックスの値を変更した時はシグナルを発行して欲しくない」という感じで、特定の処理の時だけシグナルを発行して欲しくないとき、どうやったらシグナルの発行を抑えられるのか調べてみました。

QSignalBlocker を使う方法

QSignalBlocker のコンストラクタにシグナルの発行を抑えたいオブジェクトを渡してやります。

const QSignalBlocker blocker(ui->spinBox);

QSignalBlocker のインスタンスを作ると、このインスタンスが生きているうちは、引数に渡したオブジェクトのシグナルは抑えられます。

破棄されたタイミングで、オブジェクトのシグナルのブロック状態は QSignalBlocker のコンストラクタが実行される前の状態に戻されます。

QObject::blockSignals を使う方法

QObject::blockSignals(bool block) を使った方法は以下のようになります。

const bool wasBlocked = ui->spinBox->blockSignals(true);
/* 何らかの処理 */
ui->spinBox->blockSignals(wasBlocked);

blockSignals に true を渡してやると、そのオブジェクトのシグナルは抑えられます。この時、 blockSignals は今現在のシグナルのブロックの状態を返すのでとっておいて、用が済んだらこれを使って元に戻して上げます。

サンプル

スピンボックスのアップダウンボタンで値を変えた時はシグナルを発行して、自前で用意したプッシュボタン(+、ー)で変更した時はシグナルを発行しないサンプルをGitHubに上げておきました。

GitHub - SignalBlockTest

参考

Qt Documentation - QSignalBlocker Class
Qt Documentation - QObject Class (blockSignal)