この質問は、問題に遭遇したことがない人にとっては明らかです。
VTV で選択の変更を処理する必要があります。ノードのフラット リストがあります。いつでも現在選択されているすべてのノードで何かをする必要があります
- ユーザーがノードをクリックします。
- ユーザー Shift/Ctrl キーを押しながらノードをクリックします。
- ユーザーは矢印キーを使用してリストをナビゲートします。
- ユーザーがマウスをドラッグして選択範囲を作成
- ユーザーが空のスペースをクリックするか、選択されたノードのみを Ctrl キーを押しながらクリックして、選択を削除します。
これは、Windows エクスプローラーと同様に、最も一般的で予想される動作です。マウスやキーボードでファイルを選択すると、情報パネルにそのプロパティが表示されます。それ以上は必要ありません。そして、これは私が立ち往生するところです。
私の研究のいくつかは次のとおりです。
最初は OnChange を使用しました。うまく機能しているように見えましたが、奇妙なちらつきに気付き、最も一般的なシナリオ (1 つのノードが選択され、ユーザーが別のノードをクリックする) で OnChange が 2 回発生することがわかりました。
- 古いノードが選択解除されたとき。この時点では、選択は空です。GUI を更新して、すべてのプロパティの代わりに「何も選択されていません」というラベルを表示します。
- 新しいノードが選択されたとき。GUI を再度更新して、新しいノードのプロパティを表示します。したがって、ちらつき。
この問題はググることができたので、人々は OnChange の代わりに OnFocusChange と OnFocusChanging を使用していることがわかりました。ただし、この方法は単一選択でのみ機能します。複数選択、ドラッグ選択、およびナビゲーション キーでは、これは機能しません。場合によっては、Focus イベントがまったく発生しないこともあります (たとえば、空のスペースをクリックして選択が削除された場合)。
これらのハンドラーがさまざまなシナリオでどのように起動されるかを知るために、デバッグ出力の調査を行いました。私が見つけたのは、目に見える感覚やパターンのない完全な混乱です。
C OnChange
FC OnFocusChange
FCg OnFocusChanging
- nil parameter
* non-nil parameter
! valid selection
Nodes User action Handlers fired (in order)
selected
0 Click node FCg-* C*!
1 Click same FCg**
1 Click another C- FCg** C*! FC*
1 Ctlr + Click same FCg** C*!
1 Ctrl + Click another FCg** C*! FC*
1 Shift + Click same FCg** C*!
1 Shift + Click another FCg** C-! FC*
N Click focused selected C-! FCg**
N Click unfocused selected C-! FCg** FC*
N Click unselected C- FCg** C*! FC*
N Ctrl + Click unselected FCg** C*! FC*
N Ctrl + Click focused FCg** C*!
N Shift + Click unselected FCg** C-! FC*
N Shift + Click focused FCg** C-!
1 Arrow FCg** FC* C- C*!
1 Shift + Arrow FCg** FC* C*!
N Arrow FCg** FC* C- C*!
N Shift + Arrow (less) C*! FCg** FC*
N Shift + Arrow (more) FCg** FC* C*!
Any Ctrl/Shift + Drag (more) C*! C-!
0 Click empty -
1/N Click Empty C-!
N Ctrl/Shift + Drag (less) C-!
1 Ctrl/Shift + Drag (less) C-!
0 Arrow FCg** FC* C*!
これはかなり読みにくいです。簡単に言うと、特定のユーザー アクションに応じて、3 つのハンドラー (OnChange、OnFocusChange、および OnFocusChanging) がランダムなパラメーターを使用してランダムな順序で呼び出されます。FC と FCg は、まだイベントを処理する必要があるときに呼び出されないことがあるため、OnChange を使用する必要があることは明らかです。
しかし、次のタスクは次のとおりです。OnChange 内では、この呼び出しを使用する必要があるのか、次の呼び出しを待つ必要があるのか わかりません。選択したノードのセットが中間的で役に立たない場合があり、それを処理すると、GUI のちらつきや不要な重い計算が発生することがあります。
「!」でマークされた呼び出しのみが必要です。上の表で。しかし、それらを内部から区別する方法はありません。例: 私が "C-" (OnChange、Node = nil、SelectedCount = 0) にいる場合、ユーザーが選択を削除した (その後、それを処理する必要がある) か、別のノードをクリックした (その後、待機する必要がある) ことを意味する可能性があります。新しい選択が形成されたときの次の OnChange 呼び出し)。
とにかく、私の研究が不要であることを願っています。解決策をシンプルかつ明確にする何かを見逃していることを願っています。皆さんが私のためにそれを指摘してくれることを願っています. 私がこれまでに持っているものを使用してこのパズルを解くと、ひどく信頼性の低い複雑なロジックが生成されます.
前もって感謝します!