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

NatTable中如何正确拖拽已多选的行?

NatTable多行拖拽选中异常的解决方案

问题根源

你遇到的问题核心是NatTable的事件优先级:鼠标按下事件会先触发Ctrl+点击切换行选中的逻辑,再触发拖拽判断。当你按住Ctrl拖拽已选中的行时,按下鼠标的瞬间就会把当前点击的行从选中集合中移除,导致最终只有剩余行被拖拽。

解决步骤

1. 拦截拖拽场景下的选中切换逻辑

修改SelectionLayer的鼠标绑定,让Ctrl+点击切换选中的行为只在非拖拽场景生效:

// 先清除默认的Ctrl+点击选中绑定
selectionLayer.configureMouseClickBindings();
MouseBindingRegistry bindingRegistry = selectionLayer.getMouseBindingRegistry();

// 找到默认的Ctrl+点击切换行选中的绑定并移除
Optional<MouseBinding> targetBinding = bindingRegistry.getMouseBindings().stream()
    .filter(binding -> binding.getAction() instanceof SelectRowAction)
    .filter(binding -> {
        SelectRowAction action = (SelectRowAction) binding.getAction();
        return !action.isShiftMask() && action.isCtrlMask();
    })
    .findFirst();
targetBinding.ifPresent(bindingRegistry::unregisterMouseBinding);

// 注册自定义绑定:仅当非拖拽状态时,才触发Ctrl+点击切换选中
bindingRegistry.registerMouseBinding(
    new MouseEventMatcher(SWT.CTRL, MouseEventMatcher.ROW, MouseEventMatcher.LEFT_BUTTON) {
        @Override
        public boolean matches(NatTable natTable, MouseEvent event) {
            // 拖拽状态下不触发选中切换
            return super.matches(natTable, event) && !natTable.getDragSource().isDragging();
        }
    },
    new SelectRowAction(false, true)
);

2. 强制拖拽时携带所有选中行

自定义DragSourceListener,确保拖拽起始时获取的是SelectionLayer中所有选中的行,而非仅当前点击的行:

DragSource dragSource = new DragSource(natTable, DND.DROP_MOVE);
dragSource.setTransfer(new RowTransfer());

dragSource.addDragListener(new DragSourceAdapter() {
    @Override
    public void dragStart(DragSourceEvent event) {
        List<Integer> selectedRows = selectionLayer.getSelectedRowIndexes();
        // 无选中行则取消拖拽
        event.doit = !selectedRows.isEmpty();
        if (event.doit) {
            // 将所有选中行作为拖拽数据
            event.data = selectedRows.toArray(new Integer[0]);
        }
    }

    @Override
    public void dragSetData(DragSourceEvent event) {
        // 再次确认拖拽数据为全选中行
        event.data = selectionLayer.getSelectedRowIndexes().toArray(new Integer[0]);
    }
});

3. 可选:自定义选中行为增强判断

如果上述方案仍有边界问题,可以自定义SelectRowAction,在执行选中切换前判断是否为拖拽操作:

public class DragAwareSelectRowAction extends SelectRowAction {
    public DragAwareSelectRowAction(boolean shiftMask, boolean ctrlMask) {
        super(shiftMask, ctrlMask);
    }

    @Override
    public void run(NatTable natTable, MouseEvent event) {
        // 若当前处于拖拽状态,直接跳过选中切换逻辑
        if (natTable.getDragSource() != null && natTable.getDragSource().isDragging()) {
            return;
        }
        super.run(natTable, event);
    }
}

使用时替换之前的SelectRowAction即可。

原理说明

通过修改事件触发条件,让选中切换逻辑和拖拽逻辑互斥:

  • 拖拽起始时,拦截选中切换的触发
  • 强制拖拽数据从SelectionLayer的全选中集合中获取,而非依赖点击事件的目标行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:13:28