6

我是 SWT/JFace 技术的新手,我发现了一个让我发疯的问题。在 Eclipse RCP 应用程序中,我有一个视图,其中放置了一个带有 JFace TreeViewer 的 SWT 树,它通过标签提供程序提供标签和图标。根据客户要求,树的底色为深蓝色,字体颜色为白色。This combination of colours results in a bad visualization of a node's text when the node is selected, the text does not fit the tree region and we place the mouse pointer over the node. 不知何故,出现了“本机突出显示”。这可以在下图中显示。

在此处输入图像描述

另一方面,当我们放置鼠标的节点未被选中时,不会发生此问题。突出显示会更改字体的颜色以使其更明显。这可以在下图中显示。

在此处输入图像描述

在做了一些研究之后,我发现通过为事件添加一个监听器,SWT.EraseItem我可以修改所选节点的背景颜色,然后禁用选择。这使我可以定义自己的选择背景样式,并禁用 的SWT.SELECTED标志,event.detail以强制操作系统在未选择节点时突出显示。

private final class EraseItemListener implements Listener {

    public void handleEvent(Event event) {
        // Only perform the node highlight when it is selected.
        if ((event.detail & SWT.SELECTED) == SWT.SELECTED) {
            // Modify background, emulate Windows highlighting.

            ...

            // Set Windows that we do not want to draw this item as a selection (we have already highlighted the item in our way).
            event.detail &= ~SWT.SELECTED;
        }
    }
}

这个“解决方案”可能是合理的。我看到的主要缺点是我的选择样式仅适用于 Windows 7 默认视觉主题。对于那些“Windows 经典”或“高对比度”,我会遇到可视化问题。此外(这是最烦人的问题),为SWT.EraseItem(即使没有处理事件的代码)添加侦听器的事实产生了两个新问题。

  1. 这使得 SWT 或 JFace 将树节点的图标绘制在错误的位置,如下图所示。

    在此处输入图像描述

  2. 树的根节点的突出显示是完全错误的。如下图所示,节点似乎以两种不同的方式突出显示,并且重复了图标。

    在此处输入图像描述

我的问题基本上是两个。

  1. 您认为主要问题有更简单的解决方案吗?我想要以与第二张图像相同的方式显示选定的节点(第一张图像中的那个)。我想更改所选节点的前景色以使其更明显。

  2. 如果使用该SWT.EraseItem方法,有没有办法在正确的位置显示图标?这种行为是已知的错误吗?

提前致谢。

4

2 回答 2

2

如果您使用基于StyledCellLabelProvider(可能基于DelegatingStyledCellLabelProvider)的标签提供程序,您可以指定COLORS_ON_SELECTION在选择时保留正常颜色。

如果这还不够好(这里没有要测试的 Windows),您可以覆盖该paint方法 - 您可以再次尝试使用event.detail &= ~SWT.SELECTED来抑制正常的选择处理,甚至自己处理绘制。

于 2014-01-22T10:04:52.940 回答
0

刚刚偶然发现这篇旧帖子并意识到它与我最近在 eclipse 上打开的一个错误相匹配。

我使文本具有正确颜色的解决方法是使用 PaintListener(在树中注册SWT.PaintItem)用不同的颜色绘制文本:

private static class TreePaintListener implements Listener {
    @Override
    public void handleEvent(Event event) {
        boolean isSelected = (event.detail & SWT.SELECTED) != 0;
        if (isSelected && event.item instanceof TreeItem) {         
            TreeItem treeItem = (TreeItem) event.item;
            Tree parent = treeItem.getParent();


            GC gc = event.gc;
            Color foreground = null/* Some Color */;
            gc.setForeground(foreground);

            Rectangle imageBounds = treeItem.getImageBounds(0);
            Rectangle textBounds = treeItem.getTextBounds(0);
            Point stringExtent = gc.stringExtent(treeItem.getText());

            int offsetX = imageBounds.width != 0 ? imageBounds.height - imageBounds.width : 0;
            int offsetY = (textBounds.height - stringExtent.y) / 2;

            int x = textBounds.x + offsetX;
            int y = textBounds.y + offsetY;

            if (gc.getClipping().contains(x, y)) {
                gc.drawString(treeItem.getText(), x, y);
            }
        }
    }
}

但是当定义了多个列时它仍然行为不端(只有第一个被绘制),并且根据操作系统和 DPI,计算可能有点偏离。

于 2019-05-31T08:46:28.270 回答