Java SWT Tree和TreeItem:删除或更改展开/折叠指示器的绘图行为
我在SWT(无JFace)中工作,我正在尝试自定义使用侧边栏的树的行为 树中的顶级项不应是可选的;他们基本上是头球。只能选择这些项目的子项。因此,我希望UI的行为方式能够表明这一点;单击其中一个顶级项目应展开或折叠,但不应在指示器改变其状态和孩子的可见性改变之外提供任何形式的视觉反馈 问题似乎在于,在OSX上,展开/折叠指示器是一个三角形(不知道它是图像还是unicode字符),它要么指向右,要么指向下,但也基于“选择”状态着色。我已经成功地覆盖了顶层项目的所有相关行为,除了箭头改变颜色Java SWT Tree和TreeItem:删除或更改展开/折叠指示器的绘图行为,java,macos,user-interface,drawing,swt,Java,Macos,User Interface,Drawing,Swt,我在SWT(无JFace)中工作,我正在尝试自定义使用侧边栏的树的行为 树中的顶级项不应是可选的;他们基本上是头球。只能选择这些项目的子项。因此,我希望UI的行为方式能够表明这一点;单击其中一个顶级项目应展开或折叠,但不应在指示器改变其状态和孩子的可见性改变之外提供任何形式的视觉反馈 问题似乎在于,在OSX上,展开/折叠指示器是一个三角形(不知道它是图像还是unicode字符),它要么指向右,要么指向下,但也基于“选择”状态着色。我已经成功地覆盖了顶层项目的所有相关行为,除了箭头改变颜色 我使
- 我使用了一个
监听器来连接到背景绘图,这样背景就不会改变颜色。这正如预期的那样有效SWT.EraseItem
- 我使用了
侦听器来确保顶级项中的文本不会改变颜色。这与预期一样有效,但似乎对指标没有任何影响;我甚至尝试不重置GC的前景色,但指示器的颜色仍然会改变:SWT.PaintItem
- 只需在指示器顶部绘制一个矩形。无论我将PaintListener连接到什么,指示器似乎总是在顶部
- 在选择事件类型上使用侦听器,检查
是否为顶级项之一,然后摆弄事件位和重画标志。这似乎根本不起作用;这种行为完全不可预测。代码如下所示:event.item
因为重画标志只是一个提示,所以有时它被正确设置,而另一些则没有。它要么没有效果,要么被锁定在一种状态,在该状态下,侧边栏中没有任何内容被重新绘制sideBar.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { TreeItem eventItem = (TreeItem) event.item; if(sideBarRoots.contains(event.item)) { event.detail = 0; event.type = 0; event.doit = false; sideBar.setRedraw(false); } else { sideBar.setRedraw(true); event.type = SWT.Selection; event.doit = true; } } });
我知道很多这种行为与底层本机小部件的行为高度耦合,但我想知道是否有任何方法可以在不从头开始滚动自定义小部件的情况下获得我想要的行为?我认为在您这样的情况下,理想情况下不应该允许在树头上进行选择 您可以通过不允许单击来取消选择事件。但这可能是一个有点笨拙的实现,特别是对于键导航 如果可能的话,更安全的方法是在选择树父节点时移动选择。因此,如果通过键盘或鼠标选择父节点,应该是这样的:展开节点并将选择移动到第一个子节点
通过这种方式,您可以避免所有隐藏选择状态的绘制技巧。您是否尝试过在不同的操作系统上运行应用程序,只是为了查看它的外观?我的猜测是,你不能对箭头做太多的处理,因为它们是由操作系统来处理的。@Baz不,但是在Windows上,IIRC在一个小框内使用“加减”图像,因此行为完全不同。我想我将不得不推出我自己的小部件,它是由列表和标签构建的,带有自定义图形。+1但如果“类别元素”没有子元素,该怎么办?我认为在这种情况下,选择应该自动转移到最后记住的选择,或者,如果没有可选择的内容,我们应该从树中删除选择。@WaqasIlyas我同意,理想情况下,它不应该是可选择的,但这不是我在上面粘贴的代码中尝试的吗?就像我说的,那个代码实际上不起作用。如果有其他方法来实现我所寻找的,请告诉我。我想我可以将侦听器直接附加到TreeItem而不是Tree上。@DougStephen您尝试的是通过绘图来伪造未选择的行为。我的意思是,如果您确保该项实际上没有在树中被选中,那么您就不需要隐藏与所选项相关的所有行为,这将使事情变得更容易。类别元素获得选择后,立即将选择移动到其他位置或将其删除。您应该能够单独在选择侦听器中执行此操作,并且不需要所有的绘制/擦除事件处理。@WaqasIlyas是对的,但是如果您在选择侦听器中查看上面的内容,我会立即将事件详细信息和事件类型设置为0(这将删除SWT.SELECTED和SWT.selection位,相当于SWT.NONE和SWT.NONE),然后我将事件的doit设置为false。因此,即使注释掉对
setRedraw
的调用,该代码仍然不起作用。我还尝试将选择重新分配到null
,这会在本机代码端出现无效的内存访问错误。是否有其他方法阻止选择事件的传播?