このページでは

イベントシステム

Qt において、イベントとは、抽象クラス `QEvent ` を継承したオブジェクトであり、アプリケーション内部で発生した事象、あるいはアプリケーションが認識する必要がある外部の活動の結果として発生した事象を表します。 イベントは、QObject のサブクラスのどのインスタンスでも受信および処理できますが、特にウィジェットに関連しています。このドキュメントでは、一般的なアプリケーションにおけるイベントの配信と処理方法について説明します。

イベントの配信方法

イベントが発生すると、Qt は、それを表すイベントオブジェクトを作成します。これは、適切な `QEvent ` サブクラスのインスタンスを生成し、その `event()` 関数を呼び出すことで、特定の `QObject `(またはそのサブクラスのいずれか)のインスタンスにイベントを配信します。

この関数はイベント自体を処理するものではなく、配信されたイベントのタイプに基づいて、その特定のイベントタイプに対応するイベントハンドラを呼び出し、イベントが受け入れられたか無視されたかに応じて応答を送信します。

QMouseEvent やQKeyEvent などの一部のイベントはウィンドウシステムから発生し、QTimerEvent などの一部のイベントは他のソースから発生し、また、アプリケーション自体から発生するものもあります。

イベントの種類

ほとんどのイベントタイプには専用のクラスがあり、特にQResizeEvent 、QPaintEvent 、QMouseEvent 、QKeyEvent 、QCloseEvent などが挙げられます。各クラスはQEvent を継承し、イベント固有の関数を追加しています。例えば、QResizeEvent は、ウィジェットがその寸法がどのように変更されたかを把握できるようにするために、size() およびoldSize() を追加しています。

一部のクラスは、複数の実際のイベントタイプをサポートしています。QMouseEvent は、マウスボタンの押下、ダブルクリック、移動、およびその他の関連操作をサポートしています。

各イベントには、QEvent::Type で定義された関連するタイプがあり、これは、特定のイベントオブジェクトがどのサブクラスから構築されたかを迅速に判断するための、便利な実行時タイプ情報源として使用できます。

プログラムは多様かつ複雑な方法で反応する必要があるため、Qtのイベント配信メカニズムは柔軟に設計されています。QCoreApplication::notify()のドキュメントにはその全容が簡潔にまとめられています。Qt Quarterlyの記事 「Another Look at Events」では、これについてより詳しく解説されています。ここでは、アプリケーションの95%に対応できる程度の説明を行います。

イベントハンドラ

イベントが配信される通常の方法は、仮想関数を呼び出すことです。たとえば、QPaintEvent は、QWidget::paintEvent()を呼び出すことで配信されます。この仮想関数は、通常はウィジェットの再描画を行うなど、適切に対応する役割を担っています。仮想関数の実装において必要な処理をすべて行わない場合は、基底クラスの実装を呼び出す必要があるかもしれません。

たとえば、次のコードは、カスタムチェックボックスウィジェットでのマウスの左ボタンクリックを処理し、それ以外のボタンのクリックはすべて基底クラスである `QCheckBox ` クラスに渡しています。

void MyCheckBox::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        // handle left mouse button here
    } else {
        // pass on other buttons to base class
        QCheckBox::mousePressEvent(event);
    }
}

基底クラスの関数を置き換えたい場合は、すべてを自分で実装する必要があります。しかし、基底クラスの機能を拡張したいだけの場合、必要な部分を実装し、処理したくないケースについては基底クラスを呼び出してデフォルトの挙動を取得します。

場合によっては、イベント固有の関数が存在しない、あるいはその関数だけでは不十分なことがあります。最も一般的な例は、Tabキーの押下です。通常、QWidget はこれらをインターセプトしてキーボードフォーカスを移動させますが、一部のウィジェットでは、自身でTabキーを処理する必要があります。

このようなオブジェクトは、汎用イベントハンドラであるQObject::event()を再実装し、通常の処理の前または後に独自のイベント処理を行うか、あるいはその関数を完全に置き換えることができます。Tabキーを解釈すると同時に、アプリケーション固有のカスタムイベントも持つという非常に珍しいウィジェットでは、次のようなevent()関数が含まれる場合があります:

bool MyWidget::event(QEvent *event)
{
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);
        if (ke->key() == Qt::Key_Tab) {
            // special tab handling here
            return true;
        }
    } else if (event->type() == MyCustomEventType) {
        MyCustomEvent *myEvent = static_cast<MyCustomEvent *>(event);
        // custom event handling here
        return true;
    }

    return QWidget::event(event);
}

なお、QWidget::event() は、処理されなかったすべてのケースに対して依然として呼び出され、その戻り値はイベントが処理されたかどうかを示します。true の値が返されると、そのイベントが他のオブジェクトに転送されるのを防ぎます。

イベントフィルタ

オブジェクトによっては、別のオブジェクトに配信されるイベントを監視し、場合によってはそれをインターセプトする必要がある場合があります。たとえば、ダイアログでは、特定のウィジェットに対するキー入力をフィルタリングすることがよくあります。リターンキーの処理を変更する場合などがその例です。

QObject::installEventFilter()関数は、イベントフィルタを設定することでこれを可能にし、指定されたフィルタオブジェクトが、QObject::eventFilter()関数内でターゲットオブジェクト向けのイベントを受け取るようにします。イベントフィルタは、ターゲットオブジェクトよりも先にイベントを処理できるため、必要に応じてイベントを検査したり破棄したりすることができます。既存のイベントフィルタは、QObject::removeEventFilter()関数を使用して削除できます。

フィルタオブジェクトのeventFilter()の実装が呼び出されると、そのオブジェクトはイベントを受け入れるか拒否するかを選択し、イベントのさらなる処理を許可するか拒否するかを決めることができます。 すべてのイベントフィルタがイベントのさらなる処理を許可した場合(それぞれがfalse を返す場合)、そのイベントはターゲットオブジェクト自体に送信されます。いずれかのフィルタが処理を中止した場合(true を返す場合)、ターゲットおよびそれ以降のイベントフィルタは、そのイベントを一切受け取ることができません。

bool FilterObject::eventFilter(QObject *object, QEvent *event)
{
    if (object == target && event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_Tab) {
            // Special tab handling
            return true;
        } else
            return false;
    }
    return false;
}

上記のコードは、特定のターゲットウィジェットに送信されるTabキーの押下イベントをインターセプトする別の方法を示しています。この場合、フィルタは関連するイベントを処理し、true を返してそれ以上の処理を停止させます。その他のすべてのイベントは無視され、フィルタはfalse を返すことで、ターゲットウィジェットにインストールされている他のイベントフィルタを経由して、それらのイベントがターゲットウィジェットに送信されることを許可します。

また、QApplication またはQCoreApplication オブジェクトにイベントフィルタをインストールすることで、アプリケーション全体のすべてのイベントをフィルタリングすることも可能です。このようなグローバルなイベントフィルタは、オブジェクト固有のフィルタよりも先に呼び出されます。これは非常に強力ですが、アプリケーション全体のすべてのイベントの配信を遅くしてしまいます。一般的には、代わりに前述の他の手法を使用すべきです。

イベントの送信

多くのアプリケーションでは、独自のイベントを作成して送信したい場合があります。適切なイベントオブジェクトを構築し、QCoreApplication::sendEvent() およびQCoreApplication::postEvent() を使用して送信することで、Qt 独自のイベントループとまったく同じ方法でイベントを送信できます。

sendEvent()はイベントを即座に処理します。この関数が戻る時点で、イベントフィルタやオブジェクト自体がすでにイベントを処理済みとなっています。多くのイベントクラスには、isAccepted()という関数が用意されており、最後に呼び出されたハンドラによってイベントが受け入れられたか拒否されたかを確認できます。

postEvent() は、後でディスパッチされるよう、イベントをキューに投稿します。次に Qt のメインイベントループが実行されると、いくつかの最適化を施した上で、投稿されたすべてのイベントがディスパッチされます。たとえば、リサイズイベントが複数ある場合、それらは 1 つに圧縮されます。 ペイントイベントについても同様です。QWidget::update() はpostEvent() を呼び出し、これによりちらつきが解消され、複数の再描画が回避されることで処理速度が向上します。

postEvent()はオブジェクトの初期化中にも使用されます。これは、投稿されたイベントが通常、オブジェクトの初期化完了直後にディスパッチされるためです。 ウィジェットを実装する際には、イベントがそのライフサイクルの非常に早い段階で配信される可能性があることを認識しておくことが重要です。そのため、コンストラクタ内では、イベントを受信する可能性が生じる前に、メンバー変数を早めに初期化するようにしてください。

カスタム型のイベントを作成するには、QEvent::User より大きいイベント番号を定義する必要があります。また、カスタムイベントに関する特定の情報を渡すために、QEvent をサブクラス化する必要がある場合もあります。詳細については、QEvent のドキュメントを参照してください。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.