You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SWT Tree控件整行悬停与选中颜色设置问题

SWT Tree 整行背景色覆盖需求

已为SWT Tree控件添加SWT.EraseItem监听器,用于自定义选中、悬停状态的颜色。目前颜色仅作用于树项的文本区域,需要修改为覆盖Tree控件的整行宽度。

参考效果:选中或悬停树项时,背景色填充Tree控件的整个横向范围,包含缩进区域在内的整行。

现有实现代码:

tree.addListener(SWT.EraseItem, new Listener() {

    @Override
    public void handleEvent(Event event) {
        if ((event.detail & SWT.SELECTED) != 0 && (event.detail & SWT.MouseHover) != 0) {

            int width = getBounds().width;
            GC gc = event.gc;
            gc.setForeground(new Color(Display.getCurrent(), 0, 0, 0));
            gc.setBackground(new Color(Display.getCurrent(), 213, 215, 219));
            gc.fillRectangle(0, event.y, width, event.height);

            event.detail &= ~SWT.MouseHover;
            event.detail &= ~SWT.SELECTED;
        }
        if ((event.detail & SWT.SELECTED) != 0 && !tree.isFocusControl()) {
            int width = tree.getClientArea().width;
            GC gc = event.gc;
            gc.setForeground(new Color(Display.getCurrent(), 0, 0, 0));
            gc.setBackground(new Color(Display.getCurrent(), 230, 232, 235));
            gc.fillRectangle(0, event.y, width, event.height);
            event.detail &= ~SWT.SELECTED;
        }
        if ((event.detail & SWT.MouseHover) != 0) {
            int width = tree.getClientArea().width;
            GC gc = event.gc;
            gc.setForeground(new Color(Display.getCurrent(), 0, 0, 0));
            gc.setBackground(new Color(Display.getCurrent(), 213, 215, 219));
            gc.fillRectangle(0, event.y, width, event.height);
            event.detail &= ~SWT.MouseHover;
        }

        if ((event.detail & SWT.SELECTED) != 0) {
            int width = tree.getClientArea().width;
            GC gc = event.gc;
            gc.setForeground(new Color(Display.getCurrent(), 0, 0, 0));
            gc.setBackground(new Color(Display.getCurrent(), 192, 235, 237));
            gc.fillRectangle(0, event.y, width, event.height);
            event.detail &= ~SWT.SELECTED;
        }

        Color previousForegroundColor = event.gc.getForeground();
        event.gc.setForeground(previousForegroundColor);
    }
});

问题原因及修复方案

核心问题

代码第一个条件分支中使用getBounds().width获取的是树项自身的文本区域宽度,而非Tree控件的整行宽度,导致背景色仅填充文本部分。

修复步骤

  1. 统一使用tree.getClientArea().width作为填充矩形的宽度,确保覆盖Tree控件的整个横向范围。
  2. 优化Color资源管理:优先使用系统预设颜色避免资源泄漏,或手动创建Color后在控件销毁时统一释放。
  3. 保持填充起始x坐标为0,确保从Tree控件最左侧开始填充整行。

修复后代码

tree.addListener(SWT.EraseItem, new Listener() {
    @Override
    public void handleEvent(Event event) {
        Display display = Display.getCurrent();
        GC gc = event.gc;
        int fullWidth = tree.getClientArea().width;
        int itemY = event.y;
        int itemHeight = event.height;

        // 选中且悬停状态
        if ((event.detail & SWT.SELECTED) != 0 && (event.detail & SWT.MouseHover) != 0) {
            gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
            gc.setBackground(new Color(display, 213, 215, 219));
            gc.fillRectangle(0, itemY, fullWidth, itemHeight);
            event.detail &= ~(SWT.MouseHover | SWT.SELECTED);
        }
        // 无焦点时的选中状态
        else if ((event.detail & SWT.SELECTED) != 0 && !tree.isFocusControl()) {
            gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
            gc.setBackground(new Color(display, 230, 232, 235));
            gc.fillRectangle(0, itemY, fullWidth, itemHeight);
            event.detail &= ~SWT.SELECTED;
        }
        // 单纯悬停状态
        else if ((event.detail & SWT.MouseHover) != 0) {
            gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
            gc.setBackground(new Color(display, 213, 215, 219));
            gc.fillRectangle(0, itemY, fullWidth, itemHeight);
            event.detail &= ~SWT.MouseHover;
        }
        // 有焦点时的选中状态
        else if ((event.detail & SWT.SELECTED) != 0) {
            gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
            gc.setBackground(new Color(display, 192, 235, 237));
            gc.fillRectangle(0, itemY, fullWidth, itemHeight);
            event.detail &= ~SWT.SELECTED;
        }

        // 注意:手动创建的Color需在Tree的SWT.Dispose事件中统一释放,或改用display.getSystemColor()获取系统颜色
    }
});

额外优化建议

  • 避免重复创建Color对象:提前定义全局Color变量,在Tree销毁时释放;或直接使用Display.getSystemColor()获取系统预设颜色,更安全高效。
  • 使用else if简化条件判断,避免多个分支同时触发。

内容的提问来源于stack exchange,提问作者user22061831

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:44:51