对于那些自己没有遇到问题的人来说,这个问题似乎很明显。
我需要处理VTV中的选择变化。我有一个扁平的节点列表。我需要随时处理所有当前选定的节点
- 用户点击一个节点;
- 用户按住Shift / Ctrl键单击节点;
- 用户使用箭头键导航列表;
- 用户通过拖动鼠标来创建选择
- 用户通过单击空白区域或按住Ctrl键单击唯一选定的节点来删除选择
这是最常见和预期的行为,就像Windows资源管理器一样:当您使用鼠标和/或键盘选择文件时,信息面板会显示其属性。我只需要那个。 这就是我陷入困境的地方。
我的一些研究如下。
起初我使用OnChange。它似乎工作得很好,但我注意到一些奇怪的闪烁,我发现在最常见的情况下(一个节点被选中,用户点击另一个节点)OnChange被触发两次:
- 取消选择旧节点时。此时选择为空。我刷新我的GUI以显示“没有选中”标签代替所有属性。
- 选择新节点时。我再次刷新我的GUI以显示新节点的属性。因此闪烁。
这个问题是可谷歌的,所以我发现人们使用OnFocusChange和OnFocusChanging而不是OnChange。但这种方式仅适用于单一选择。通过多个选择,拖动选择和导航键,这不起作用。在某些情况下,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*!
这很难读。简而言之,它表示根据特定的用户操作,随机参数调用三个处理程序(OnChange,OnFocusChange和OnFocusChanging)。当我仍然需要处理事件时,FC和FCg有时从不被调用,所以很明显我必须使用OnChange。
但接下来的任务是:在OnChange内部,我不知道是否应该使用此调用或等待下一个调用。有时,所选择的节点集合是中间的且无用的,并且处理它将导致GUI闪烁和/或不需要的大量计算。
我只需要标有“!”的电话在上表中。但是没有办法将它们与内部区分开来。例如:如果我在“C-”(OnChange,Node = nil,SelectedCount = 0),则可能意味着用户删除了选择(然后我需要处理它)或者他们点击了另一个节点(然后我需要等待形成新选择时的下一个OnChange调用)。
无论如何,我希望我的研究是不必要的。我希望我错过了一些可以使解决方案变得简单明了的东西,并且你们,伙计们,我会指出它。使用我到目前为止解决这个难题会产生一些非常不可靠和复杂的逻辑。
提前致谢!