You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

JFace TableViewer表头前景色仅在鼠标悬停时切换问题求助

解决SWT TableViewer表头前景色仅悬停生效的问题

我之前在做SWT TableViewer的时候也踩过这个表头颜色的坑!你遇到的问题本质是SWT的原生表头控件会在不同状态(正常、悬停、选中)下自动覆盖你设置的前景色,直接调用setForeground()根本不会生效——只有当鼠标悬停时,原生绘制逻辑暂时“让步”,你的颜色才会显示出来。

要彻底解决这个问题,我们需要接管表头的绘制逻辑,用自定义的绘制器来控制颜色,而不是依赖SWT的默认行为。下面是具体的解决方案:

步骤1:创建自定义表头标签提供器

我们需要继承TableColumnLabelProvider,重写paint方法来手动绘制表头文本和颜色:

class CustomHeaderLabelProvider extends TableColumnLabelProvider {
    private final Color headerForeground;

    public CustomHeaderLabelProvider(Color foregroundColor) {
        this.headerForeground = foregroundColor;
    }

    @Override
    public void paint(Event event, Object element) {
        // 获取当前表头列的绘制区域
        Rectangle bounds = event.getBounds();
        
        // 设置我们想要的前景色
        event.gc.setForeground(headerForeground);
        
        // 绘制表头文本(这里设置了左偏移5像素,垂直偏移2像素,可根据需求调整)
        // 第三个参数true表示自动裁剪超出区域的文本
        event.gc.drawText(getColumnText(element), bounds.x + 5, bounds.y + 2, true);
    }

    @Override
    public String getColumnText(Object element) {
        // 这里的element就是对应的TableColumn对象,返回它的文本
        return ((TableColumn) element).getText();
    }
}

步骤2:在你的UsagePart中应用自定义绘制器

接下来,在创建TableViewer和表头列的时候,为每个列设置这个自定义的标签提供器,同时要禁用SWT的默认表头绘制逻辑:

public class UsagePart { 
  private TableViewer viewer; 
  private Color headerForegroundColor; // 保存颜色引用,后续销毁时释放

  @PostConstruct 
  public void createControls(final Composite parent) { 
    final TableColumnLayout tableColumnLayout = new TableColumnLayout(); 
    parent.setLayout(tableColumnLayout); 
    viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); 
    final Table table = viewer.getTable(); 

    // 创建表头列(示例创建两列)
    TableColumn column1 = new TableColumn(table, SWT.NONE);
    column1.setText("第一列");
    TableColumn column2 = new TableColumn(table, SWT.NONE);
    column2.setText("第二列");

    // 获取我们想要的颜色(这里用系统深色蓝色,你可以替换成自定义颜色)
    Display display = parent.getDisplay();
    headerForegroundColor = display.getSystemColor(SWT.COLOR_DARK_BLUE);

    // 为每个表头列设置自定义绘制器
    column1.setLabelProvider(new CustomHeaderLabelProvider(headerForegroundColor));
    column2.setLabelProvider(new CustomHeaderLabelProvider(headerForegroundColor));

    // 关键:确保表头可见,并且可以设置表头背景色(可选)
    table.setHeaderVisible(true);
    table.setHeaderBackground(display.getSystemColor(SWT.COLOR_WHITE));

    // 其他初始化逻辑(比如设置内容提供器、输入数据等)
    // viewer.setContentProvider(...);
    // viewer.setInput(...);
  }

  // 记得在部件销毁时释放颜色资源,避免内存泄漏
  @PreDestroy
  public void dispose() {
    if (headerForegroundColor != null && !headerForegroundColor.isDisposed()) {
      headerForegroundColor.dispose();
    }
  }
}

额外注意事项

  • 不同列设置不同颜色:如果需要给每个表头列设置不同的颜色,只需要在创建CustomHeaderLabelProvider时传入不同的Color对象即可。
  • 文本对齐调整:如果需要居中或右对齐文本,可以通过计算bounds的位置来调整drawText的坐标,比如居中的话可以用bounds.x + (bounds.width - event.gc.stringExtent(text).x) / 2
  • 资源释放:SWT的Color是系统资源,必须在部件销毁时调用dispose()释放,否则会造成内存泄漏,上面的代码已经在@PreDestroy方法中处理了这一点。

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

火山引擎 最新活动