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

Java SWT虚拟表格全选后滚动显示异常问题排查

SWT虚拟表格全选后滚动显示异常问题

我开发的Java SWT应用包含虚拟表格,用户搜索关键词后表格展示匹配的文档列表。点击首列表头可全选该列复选框,但全选后滚动表格时,仅全选操作时可见的项正常显示,其他项显示为空;不过点击空白区域仍能显示文档详情。调试发现调用table.redraw()未实现预期的全表重绘效果。


问题根源

SWT虚拟表格(SWT.VIRTUAL)的核心机制是按需加载行数据:只有可见行才会被初始化,滚动时会复用TableItem并触发SWT.SetData事件重新填充数据。当前代码存在两个关键问题:

  • toggleSelection方法仅修改了当前已初始化的TableItem(即可见行)的复选框状态,未初始化的行(不可见)在滚动触发SWT.SetData时,会调用Column.getImage(element)重新获取图片,而该方法未考虑全选状态,导致显示默认的未选中状态。
  • 全选状态仅在UI层面修改TableItem,未与数据模型绑定,导致数据和UI状态不一致。

解决方案

需要将全选状态与数据模型关联,并在SWT.SetData事件中根据全选状态和单个项的选中状态渲染复选框,同时触发全表重新初始化而非仅重绘。

修改后的关键代码

1. 重写toggleSelection方法,更新数据模型并触发全表重新初始化

private void toggleSelection() {
    Display.getDefault().asyncExec(() -> {
        // 清除所有已初始化的行,滚动时会重新触发SWT.SetData事件
        table.clearAll();
    });
    
    // 更新选中集合,保证数据模型与UI状态一致
    ResultPanel.selDocument.clear();
    if (isAllSelected) {
        // 全选时添加所有文档
        ResultPanel.selDocument.addAll((List<ResultDocument>) (List<?>) elements);
    }
}

2. 修改SWT.SetData事件处理逻辑,根据状态渲染复选框

table.addListener(SWT.SetData, new Listener() {
    public void handleEvent(org.eclipse.swt.widgets.Event event) {
        if (event.index < 0 || event.index >= elements.size())
            return;
        Util.checkThat(!columns.isEmpty());
        TableItem item = (TableItem) event.item;
        E element = elements.get(event.index);
        
        for (int iCol = 0; iCol < columns.size(); iCol++) {
            Column<E> column = columns.get(iCol);
            item.setText(iCol, column.getLabel(element));
            
            // 首列复选框渲染逻辑:优先判断全选状态,再判断单个项是否选中
            if (iCol == 0) {
                if (isAllSelected) {
                    item.setImage(iCol, Img.CHECKBOX_CHECKED.get());
                } else {
                    boolean isSelected = ResultPanel.selDocument.contains(element);
                    item.setImage(iCol, isSelected ? Img.CHECKBOX_CHECKED.get() : Img.CHECKBOX_UNCHECKED.get());
                }
            } else {
                item.setImage(iCol, column.getImage(element));
            }
            
            item.setForeground(iCol, column.getForeground(element));
            item.setBackground(iCol, column.getBackground(element));
        }
        item.setData(element);
    }
});

3. 优化表头点击事件,简化全选状态切换逻辑

tableColumn.addListener(SWT.Selection, event -> {
    isAllSelected = !isAllSelected;
    tableColumn.setImage(isAllSelected ? Img.CHECKBOX_CHECKED.get() : Img.CHECKBOX_UNCHECKED.get());
    toggleSelection();
});

关键说明

  • table.clearAll()会清除所有已初始化的TableItem,滚动时会重新触发SWT.SetData事件,确保所有行都使用最新的全选状态渲染;
  • 将选中状态与ResultPanel.selDocument集合绑定,保证UI展示和数据模型的一致性;
  • 首列复选框优先判断全局全选标记,再判断单个项的选中状态,避免状态冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:56:01