イベントフィルタとは?
Qtのイベントフィルタは、あるオブジェクトに対して他のオブジェクトのイベントをインターセプトして処理する仕組みを提供します。イベントが対象オブジェクトに到達する前にキャッチし、処理内容を変更したり、イベントを完全にブロックすることが可能です。
イベントフィルタの利点
- 複数のオブジェクトに共通してイベント処理を適用できる。
- 対象オブジェクトのコード変更なしにイベントをグローバルに処理できる。
- イベントの改変、遮断、遅延実行などの高度な制御が可能。
イベントフィルタの実装方法
イベントフィルタを実装するには、QObjectを継承したクラスを作成し、eventFilter()メソッドをオーバーライドします。このメソッドはイベントが到達した際に呼び出され、処理結果に応じてtrueまたはfalseを返します。
主な関数
void QObject::installEventFilter(QObject *filterObj)
void QObject::removeEventFilter(QObject *obj)
イベントフィルタの使用方法
1. 親ウィジェットでイベントを監視する
子オブジェクトのイベントを親クラス内で監視・処理したい場合、イベントフィルタをインストールしてeventFilter()を実装します。この方法では、子クラスのイベント処理をオーバーライドする必要がなくなります。
以下の例では、カスタムLineEditとButtonがイベントを独自に処理しています。親ウィジェットMainWindowはイベントフィルタをインストールし、特定のイベントを遮断します。
ヘッダファイル(MainWindow.h)
class CustomLineEdit : public QLineEdit {
Q_OBJECT
public:
explicit CustomLineEdit(QWidget *parent = nullptr);
protected:
void keyPressEvent(QKeyEvent *event) override;
};
class CustomButton : public QPushButton {
Q_OBJECT
public:
explicit CustomButton(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *event) override;
};
class MainWindow : public QWidget {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
private:
void setupUI();
void setupConnections();
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
CustomLineEdit *lineEdit;
CustomButton *button;
};
実装ファイル(MainWindow.cpp)
CustomLineEdit::CustomLineEdit(QWidget *parent)
: QLineEdit(parent) {}
void CustomLineEdit::keyPressEvent(QKeyEvent *event) {
qDebug() << "CustomLineEdit::keyPressEvent" << event->key();
QLineEdit::keyPressEvent(event);
}
CustomButton::CustomButton(QWidget *parent)
: QPushButton("Click Me", parent) {}
void CustomButton::mousePressEvent(QMouseEvent *event) {
qDebug() << "CustomButton::mousePressEvent";
QPushButton::mousePressEvent(event);
}
MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {
setupUI();
this->installEventFilter(this);
lineEdit->installEventFilter(this);
button->installEventFilter(this);
}
void MainWindow::setupUI() {
lineEdit = new CustomLineEdit(this);
button = new CustomButton(this);
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(lineEdit);
layout->addWidget(button);
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event) {
if (watched == lineEdit && event->type() == QEvent::KeyPress) {
return true; // 入力イベントを遮断
}
if (watched == button && event->type() == QEvent::MouseButtonPress) {
return true; // ボタンクリックを遮断
}
if (watched == this && event->type() == QEvent::MouseButtonPress) {
qDebug() << "MainWindow mouse press filtered";
return true;
}
return QWidget::eventFilter(watched, event);
}
void MainWindow::keyPressEvent(QKeyEvent *event) {
qDebug() << "MainWindow key press";
QWidget::keyPressEvent(event);
}
2. 専用のイベントフィルタクラスを作成する
共通のイベント処理を行うためのフィルタクラスを定義します。このクラスは複数のオブジェクトに適用でき、再利用性が高くなります。
KeyPressEaterクラス
class KeyPressEater : public QObject {
Q_OBJECT
public:
explicit KeyPressEater(QObject *parent = nullptr) : QObject(parent) {}
protected:
bool eventFilter(QObject *obj, QEvent *event) override {
if (event->type() == QEvent::KeyPress) {
qDebug() << "Key press event blocked";
return true;
}
return QObject::eventFilter(obj, event);
}
};
利用例
KeyPressEater *eater = new KeyPressEater(this);
QPushButton *btn = new QPushButton("Test", this);
QLineEdit *edit = new QLineEdit(this);
btn->installEventFilter(eater);
edit->installEventFilter(eater);
3. QApplicationにイベントフィルタをインストールする
アプリケーション全体でイベントを監視するには、QApplicationオブジェクトにイベントフィルタをインストールします。
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
KeyPressEater *eater = new KeyPressEater(&app);
app.installEventFilter(eater);
MainWindow w;
w.show();
return app.exec();
}