【问题标题】:SWT Tree and TreeItem: Remove or change the drawing behavior of the expand/collapse indicatorSWT Tree 和 TreeItem:删除或更改展开/折叠指示器的绘制行为
【发布时间】:2013-02-09 09:29:30
【问题描述】:

我正在使用 SWT(没有 JFace),我正在尝试自定义使用侧边栏的 Tree 的行为。

树中的顶级项目不应该是可选择的;他们基本上是标题。只有这些项目的子项应该是可选的。因此,我希望 UI 以表明这一点的方式运行;单击这些顶级项目之一应展开或折叠,但不应在指示器更改其状态和子项的可见性更改之外提供任何类型的视觉反馈。

问题似乎是在 OS X 上,展开/折叠指示器是一个三角形(不知道它是图像还是 unicode 字符),指向右侧或向下,但也基于“选择”状态。除了改变颜色的箭头之外,我已经设法覆盖了顶级项目的所有相关行为。

  • 我使用了SWT.EraseItem 监听器连接到背景绘图,这样背景就不会改变颜色。这按预期工作。
  • 我使用了SWT.PaintItem 监听器来确保顶级项目中的文本不会改变颜色。这按预期工作,但似乎对指标没有任何影响;我什至尝试过重置 GC 的前景色,但指示器的颜色仍然会发生变化:

未选择

已选择

我尝试做的一些事情,都失败了:

  • 只需在指示器顶部绘制一个矩形。无论我将 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 他们在一个小盒子内使用“加/减”图像,因此行为完全不同。我想我将不得不推出自己的小部件,这是由带有自定义绘图的列表和标签构建的。

标签: java macos user-interface drawing swt


【解决方案1】:

我认为在您的情况下,理想情况下您应该不允许在树头上进行选择。

您可以取消选择事件,方法是不允许它可点击。但这可能是一个有点笨拙的实现,尤其是对于键导航。

如果可能的话,更安全的方法是在选择树父节点时移动选择。因此,如果通过键盘或鼠标选择了父节点,它应该像这样工作:展开节点并将选择移动到第一个子节点。

这样你可以避免所有隐藏选择状态的绘画技巧。

【讨论】:

  • +1 但是如果“类别元素”没有子元素会发生什么?
  • 我认为在这种情况下,选择应该自动转移到最后记住的选择,或者如果没有可以选择的内容,我们应该从树中删除选择。
  • @WaqasIlyas 我同意,理想情况下它根本不应该是可选的,但这不是我在上面粘贴的代码中尝试的吗?就像我说的那样,该代码实际上不起作用。如果有另一种方法来实现我正在寻找的东西,请告诉我。我想我可以将侦听器直接附加到 TreeItem 而不是 Tree。
  • @DougStephen 您正在尝试通过绘图来伪造未选择的行为。我的意思是,如果您确保项目实际上没有在树中被选中,这样您就不需要隐藏与所选项目相关的所有行为,这将使您的事情变得更容易。一旦类别元素获得选择,将选择移动到其他地方或将其删除。您应该能够单独在选择侦听器中执行此操作,并且不需要所有绘制/擦除事件处理。
  • @WaqasIlyas 是的,但是如果你看上面,在选择侦听器中,我立即将事件详细信息和事件类型设置为 0(删除了 SWT.SELECTED 和 SWT.Selection 位,相当于SWT.NONE 和 SWT.None),然后我将事件的 doit 设置为 false。因此,即使注释掉对setRedraw 的调用,该代码仍然不起作用。我还尝试将选择重新分配给null,这会在本机代码端产生无效的内存访问错误。是否有其他方法可以阻止选择事件的传播?
猜你喜欢
  • 2015-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-14
  • 2016-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多