Qt イベントのまとめ

Qt のイベントは、Qt フレームワーク全体のコア メカニズムの 1 つであり、比較的複雑でもあります。複雑と言われていますが、それ以上に機能が多く、処理方法も多く、選ぶのが難しい場合もあります。ここで、Qt のイベント メカニズムを簡単にまとめます。

Qt には、マウス イベント、キーボード イベント、サイズ変更イベント、位置移動イベントなど、さまざまな種類のイベントがあります。これらのイベントの処理方法には、実際には 2 つのオプションがあります。

1. すべてのイベントがイベント処理関数に対応する. このイベント処理関数では, 大きな分岐文を使って選択を行う. その代表例が win32 API の WndProc() 関数である.

LRESULT CALLBACK WndProc(HWND hWnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam)

この関数では、switch ステートメントを使用して、処理するメッセージ パラメータのタイプを選択する必要があります。典型的なコードは次のとおりです。

switch(message)
{
    case WM_PAINT:
        // ...
        break;
    case WM_DESTROY:
        // ...
        break;
    ...
}

この記事の利点は、 Qt開発学習教材パッケージ、テクニカル ビデオ (C++ 言語の基礎、Qt プログラミングの概要、QT シグナルとスロット メカニズム、QT インターフェイス開発イメージの描画、QT ネットワーク、QT データベース プログラミング、QT を含む) を無料で受け取ることです。プロジェクトコンバット、QSS、OpenCV、クイックモジュール、インタビュー質問など) ↓↓↓↓↓↓下記参照↓↓ 記事下部をクリックして料金を受け取る↓↓

2. 各イベントはイベント ハンドラに対応します。Qt は次のようなメカニズムを使用します。

  • マウスイベント()
  • keyPressEvent()

Qt には非常に多くのイベント処理関数があり、それらを配布する場所が必要です。それ以外の場合、Qt はどのイベントをどのイベント処理関数を呼び出すべきかをどうやって知るのでしょうか? 配信関数は event() です。明らかに、QMouseEvent が生成されると、event() 関数はそれを処理のために mouseEvent() イベント ハンドラーに配布します。

event() 関数には 2 つの問題があります。

  1. event() 関数は保護された関数です。つまり、event() をオーバーライドしたい場合は、既存のクラスを継承する必要があります。私のプログラムはマウス イベントをまったく必要とせず、プログラム内のすべてのコンポーネントがマウス イベントを処理することを許可されていません.すべてのコンポーネントを継承し、それらの event() 関数を 1 つずつ書き直す必要がありますか? 保護された関数によって引き起こされるもう 1 つの問題は、サードパーティのライブラリに基づいて開発し、相手がソース コードを提供しない場合、リンク ライブラリは 1 つだけで、他のライブラリはパッケージ化されていることです。このライブラリからコンポーネントを継承するにはどうすればよいですか?
  2. event() 関数にはある程度の制御機能がありますが、より制限的なニーズがある場合もあります。これらのコンポーネントにそのようなイベントがまったく表示されないようにしたいのです。event() 関数はインターセプトできますが、実際には QMouseEvent オブジェクトを受け取りました。集めることもできません。これの利点は、シミュレートされたシステムがそのイベントの影響をまったく受けないため、他のコンポーネントはこのイベントをまったく受信せず、独自のイベント処理関数を変更する必要がないことです。この必要性に対して私たちは何をすべきでしょうか?

これら 2 つの問題は、event() 関数では処理されません。したがって、Qt はイベント フィルターという別のソリューションを提供します。イベント フィルターを使用すると、特定のイベントを完全に削除できます。イベント フィルターは任意の QObject タイプにインストールでき、複数インストールできます。グローバル イベント フィルターを実装する場合は、QApplication または QCoreApplication にインストールできます。installEventFilter() 関数を使用してオブジェクトのイベント フィルタをインストールする場合、イベント フィルタはそのオブジェクトに対してのみ有効であり、このオブジェクトのイベントのみを eventFilter() に渡す必要があることに注意してください。フィルタリングのためのイベント フィルタの機能、他のオブジェクトは影響を受けません。QApplication オブジェクトにイベント フィルタがインストールされている場合、フィルタはプログラム内のすべてのオブジェクトに対して有効であり、オブジェクトのイベントは最初に eventFilter() 関数に渡されます。

イベント フィルターは、今提案した event() 関数の 2 つの欠点を解決できます: 1 つ目は、イベント フィルターが保護されていないため、イベント フィルターを任意の QObject サブクラスにインストールできること、2 つ目は、イベント フィルターが Event を受信して​​から処理されることです。 、イベントを除外すると、ターゲット オブジェクトはこのイベントをまったく認識しません。

実は、紹介していない別の方法があります。Qt イベントの呼び出しは、最終的には QCoreApplication::notify() 関数までさかのぼります。そのため、実際に QCoreApplication::notify() を書き直すことが最大の制御権です。この関数の宣言は次のとおりです。

virtual bool QCoreApplication::notify ( QObject * receiver, QEvent * event );

この関数はレシーバーにイベントを送信します。つまり、receiver->event(event) を呼び出します。戻り値は、レシーバーからのイベント ハンドラーです。この関数は、任意のスレッドから任意のオブジェクトの任意のイベントに対して呼び出されるため、イベント フィルターのスレッド化の問題は発生しないことに注意してください。ただし、notify() 関数は 1 つしかなく、イベント フィルターははるかに柔軟であるため、これを行うことはお勧めしません。

Qt のイベント処理を要約すると、実際には 5 つのレベルがあります。

  1. paintEvent() や mousePressEvent() などのイベント ハンドラを書き換えます。これは、最も一般的で最も単純な形式であると同時に、最も単純な機能です。
  2. event() 関数をオーバーライドします。event() 関数は、すべてのオブジェクトのイベント エントリであり、QObject および QWidget で実装されます。デフォルトでは、イベントを特定のイベント処理関数に渡します。
  3. 特定のオブジェクトにイベント フィルタをインストールします。このフィルターは、このオブジェクトが受信したイベントのみをフィルター処理します。
  4. QCoreApplication::instance() にイベント フィルターをインストールします。このフィルターは、すべてのオブジェクトのすべてのイベントをフィルタリングするため、notify() 関数と同じくらい強力ですが、複数のフィルターをインストールできるため、より柔軟です。グローバル イベント フィルターは、無効化されたコンポーネントによって発行されたマウス イベントを認識します。グローバル フィルタには問題があります。これらはメイン スレッドでしか使用できません。
  5. QCoreApplication::notify() 関数をオーバーライドします。これは最も強力で、グローバル イベント フィルターのような完全な制御を提供し、スレッドによって制限されません。ただし、グローバルに使用できるのは 1 つだけです (QCoreApplication はシングルトンであるため)。

これらのいくつかのレベルのイベント処理の呼び出しシーケンスをさらに理解するために、テスト コードを記述できます。

class Label : public QWidget
{
public:
    Label()
    {
        installEventFilter(this);
    }

    bool eventFilter(QObject *watched, QEvent *event)
    {
        if (watched == this) {
            if (event->type() == QEvent::MouseButtonPress) {
                qDebug() << "eventFilter";
            }
        }
        return false;
    }

protected:
    void mousePressEvent(QMouseEvent *)
    {
        qDebug() << "mousePressEvent";
    }

    bool event(QEvent *e)
    {
        if (e->type() == QEvent::MouseButtonPress) {
            qDebug() << "event";
        }
        return QWidget::event(e);
    }
};

class EventFilter : public QObject
{
public:
    EventFilter(QObject *watched, QObject *parent = 0) :
        QObject(parent),
        m_watched(watched)
    {
    }

    bool eventFilter(QObject *watched, QEvent *event)
    {
        if (watched == m_watched) {
            if (event->type() == QEvent::MouseButtonPress) {
                qDebug() << "QApplication::eventFilter";
            }
        }
        return false;
    }

private:
    QObject *m_watched;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    Label label;
    app.installEventFilter(new EventFilter(&label, &label));
    label.show();
    return app.exec();
}

マウス クリック後の出力は次のようになります。

QApplication::eventFilter 
eventFilter 
event 
mousePressEvent

したがって、最初にグローバル イベント フィルタが呼び出され、次にオブジェクトのイベント フィルタが呼び出され、次に event() 関数が呼び出され、最後に特定のイベント ハンドラが呼び出されることがわかります。

この記事の利点は、 Qt開発学習教材パッケージ、テクニカル ビデオ (C++ 言語の基礎、Qt プログラミングの概要、QT シグナルとスロット メカニズム、QT インターフェイス開発イメージの描画、QT ネットワーク、QT データベース プログラミング、QT を含む) を無料で受け取ることです。プロジェクトコンバット、QSS、OpenCV、クイックモジュール、インタビュー質問など) ↓↓↓↓↓↓下記参照↓↓ 記事下部をクリックして料金を受け取る↓↓

おすすめ

転載: blog.csdn.net/m0_60259116/article/details/128791583