2

長い間、モーダルダイアログがどのように実装されているのか疑問に思っていました。

例としてQtを取り上げます。(ほぼすべてのGUIツールキットにこのメカニズムがあります)

メインイベントループでは、スロットが呼び出され、このスロットでモーダルダイアログが開きます。ダイアログが閉じる前に、スロットは制御をメインイベントループに戻しません。そのため、メインイベントループがブロックされて応答しなくなると思いました。モーダルダイアログを開いても、UIを再描画したり、曲線やグラフを表示し続けたりするなど、背景のメインウィンドウはまだ機能しているため、これは明らかに当てはまりません。ユーザー入力を受け付けないようになります。

実験しました。スロットでモーダルダイアログを開きませんでしたが、そこで新しいスレッドを開始し、そのスロットでスレッドが終了するのを待ちます。これにより、メインイベントループが確実にブロックされました。

結局、モーダルダイアログはどのように実装されますか?メインイベントループのブロックを解除し、同時に呼び出しスロットをブロックするにはどうすればよいですか?

4

4 に答える 4

2

例を探している場合は、別の例を次に示します。

Tk では、イベント ループは 1 つだけです。モーダル動作 (ダイアログである必要はなく、ツールチップ、テキスト ボックスなどでもかまいません) は、メイン ウィンドウでマウスとキーボードのイベントを無視することで簡単に実装できます。イベントループがまだ実行されているため、再描画などの他のすべてのイベントは引き続き処理できます。

Tk は[grab]関数を介してこれを実装します。UI オブジェクトを呼び出すgrabと、キーボードとマウスのイベントに応答できる唯一のオブジェクトになります。基本的に他のすべてのオブジェクトをブロックします。これは、イベント ループを台無しにしません。グラブが解放されるまで、一時的にイベント ハンドラーを無効にするだけです。

grabX を実行する Unix ライクなオペレーティング システムにも、ウィンドウ システムが組み込まれていることに注意してください。そのため、UI ツールキット ライブラリだけで実装されているとは限りませんが、OS の組み込み機能である場合もあります。繰り返しますが、これは、個別のイベント ループをインスタンス化するのではなく、単純なイベントのブロック/無効化によって実装されます。これは、OSX より前の古い MacOS にも当てはまったと思います。ただし、OSXまたはWindowsについてはわかりません。多くの場合、モダリティは OS 自体によって実装されますが、Qt や Tk などのツールキットは、さまざまなプラットフォーム間で動作を標準化する独自のメカニズムを実装することがよくあります。

結論として、モダリティを実装するためにメイン イベント ループをブロックする必要はありません。イベントやイベント ハンドラをブロックするだけです。

于 2012-11-16T04:22:17.063 に答える
1

一般に、このタイプのモーダルダイアログボックスは、アプリケーションのメッセージループの代わりに独自のメッセージループを実行することによって実装されます。メインウィンドウに送信されたメッセージ(タイマーやペイントメッセージなど)は、モーダル操作中でも配信されます。

状況によっては、同じことを繰り返し繰り返さないように注意する必要があります。たとえば、永続的なフラグと組み合わせたタイマーメッセージでモーダルダイアログボックスをトリガーする場合は、タイマーメッセージが発生するたびに同じダイアログボックスを繰り返し表示しないようにする必要があります。

于 2012-11-16T03:59:49.483 に答える