web-dev-qa-db-ja.com

GUIイベントシステムを設計する適切な方法は何ですか?

私は(C++で)プロジェクトのGUIライブラリを(学習目的でも)ゼロから作成しようとしていますが、これはかなりうまく機能していますが、これが私の最初の試みなので、イベントシステムの設計はそうではないと思いますすごいね。

基本的に、イベントを処理する方法は、マウスクリックが発生するたびにすべてのウィジェット(ボタンなど)を反復処理し、マウス座標がそれらのいずれかに存在するかどうかをテストし、そうである場合はイベントコールバック(a関数ポインター)ボタンクラス自体に格納されます!

だから私は別の(より良い?)デザインを考えていました:
代わりに持っておきたいのはEvent-Queueイベントが発生するたびに(たとえばボタンがクリックされたとき)、以前と同じことを行います(つまり、クリックされたボタンを見つけます) )そして、そのイベントのオブジェクト(つまりButtonClickedEvent)を作成し、それをキューに追加して、後で、たとえばフレームをレンダリングした後に処理します。

そして、これは私がそれについて混乱しているところです。
混乱を生じさせずに全体をどのように構成する必要がありますか?言い換えれば、それを行うための標準的な方法はありますか?

私はこれに関するいくつかの情報を探していましたが、私が見つけたのは、既存のライブラリでイベントを処理する方法です(Java swing、QTなど))。

ですから、ここの誰かがそれがどのように機能するかを説明できれば、それは大いに感謝します!

1
Isho Antar

この回答では、ウィジェットはオペレーティングシステムウィンドウではなく、またオペレーティングシステムウィンドウでもないことを前提としています。


前菜:キーボード入力。

アイデアは、一部のウィジェットにはキーボードフォーカスがあるということです。それがどのウィジェットであるかを追跡します(ウィジェットがキーボード入力をサポートすることをウィジェットに示す手段がある場合、キーボードフォーカスをサポートしないウィジェットにキーボードフォーカスを与えません)。その後、イベントが登録されたら、キーボードを使用してウィジェットにイベントを送信します。


メインコース:ポインティング入力(マウス、タッチなど)。

はい、すべてを反復して境界を確認できます。それは素晴らしいことではありません。

スペース分割を使用することをお勧めします。つまり、各ノードがビューポート/ウィンドウの領域を表すツリー構造を作成します。ルートは完全な作業領域であり、葉はウィジェットの領域と一致します。これで、ツリーをナビゲートして、何がクリックされたかを確認できます。

さらに高速にすることも可能です。各ピクセル/テクセルの色がウィジェットにマップするIDであるビットマップ/テクスチャを作成します。次に、必要に応じて単にそれらを読みます。 一部のブラウザでこれが行われていることを思い出しているようですが、わかりません。

選択する構造が何であれ、ウィジェットが移動したときにそれを更新することを忘れないでください。


おかず:イベントキュー。

はいといいえ。つまり、おそらくオペレーティングシステムからのメッセージキューをすでに持っています。通常の解決策はそれに依存することです。

何かをキューに入れることに関心があるかもしれないことに注意してください(他のスレッドがそれらを使用して、UIと対話するコードを配置し、UIスレッドが処理できるようにするため)。そのためにオペレーティングシステムキューを使用できない場合(たとえば、何らかの理由でウィンドウごとに複数のキューが必要な場合)、独自のキューを作成します。


ドリンク:イベントバブリング。

ウィジェットは、イベントを処理済みまたは未処理としてマークできます。処理されない場合は、イベントをコンテナウィジェットなどに送信します。それはあなたがイベントを泡立たせることです。

ただし、プレビューイベントを処理する場合は、逆の順序で伝播します。これは、たとえば、コンテナがキーを傍受できるようにするのに役立ちます。


デザート:レンダリング。

ウィジェットが自分自身をペイントすることをどのように許可しますか? ここではオペレーティングシステムウィンドウではないと想定しています。グラフィックプリミティブを実行できるAPIを提供できます。または、グラフィックバッファ/ビットマップ/テクスチャを指定して、好きなように使用させることもできます。そして、ええ、あなたは彼らがウィンドウを奪っているのかを知っている必要があり、あなたは彼らがコードを実行するためにコールバックを実行するつもりです。おそらく、ダブルバッファリングと垂直同期も行いたいでしょう。しかし、それはこの質問の範囲を超えています。

5
Theraot