【问题标题】:Reorder table rows via Drag-and-Drop?通过拖放重新排列表格行?
【发布时间】:2016-05-17 11:59:45
【问题描述】:

我是 Eclipse RCP/插件和 SWT 的新手。我想通过拖放重新排列表格项目。

我有一个TableViewer,其中包含一个表格,其中包含我的ITask 类型的自定义元素(我的每个自定义元素都包含在TableItem 中)。我发现的所有教程都是关于树或在不同的表之间拖动,这不是我需要的。

所以我想知道如何通过拖放重新排列表格行。

【问题讨论】:

  • 您的 TableItem 是简单的文本还是 POJO?如果 ITask 是由 POJO-s 实现的,那么链接的例子对你来说是不够的。
  • @AdamHorvath 我的 ITask 元素不仅仅是简单的文本元素。它们具有显示在表格中的字符串名称字段,因此用户可以看到它们,但实际上它们包含算法和其他重要字段。

标签: java eclipse-plugin drag-and-drop swt eclipse-rcp


【解决方案1】:

它有点长,但您可以通过一些更改在您的代码中实现它。我没有包括进口; Eclipse 可以自动为您完成。

我使用了 Spring 的 BeanUtils 类,但您可以使用任何可以深度复制 POJO 的库(或编写自己的库)。我假设您的 ITask 有一个 setOrder(int) 方法并且是可序列化的(并且它符合 POJO 的条件)

您需要为您的 ITask 创建一个 Transfer-type:SimpleObjectTransfer 是 IBM 的代码,来自 Eclipse GEF。你可以谷歌/GrepCode 它。

public final class TaskTransfer extends SimpleObjectTransfer {

public static final TaskTransfer INSTANCE = new TaskTransfer();

private TaskTransfer() {
}

@Override
protected String getTypeNamePrefix() {
    return "TASK_TRANSFER_FORMAT";
}
}

一个 ViewerDropAdapter:

public class MyDropAdapter<TM extends ITask> extends ViewerDropAdapter {

private final Class<TM> targetModelClass;
private List<TM> listOfModels;

protected MyDropAdapter(Viewer viewer, Class<TM> targetModelClass, List<TM> listOfModels) {
    super(viewer);
    this.listOfModels = listOfModels;
    this.targetModelClass = targetModelClass;
}

@Override
public boolean performDrop(Object arg0) {
    boolean ret = false;
    TM targetModel = targetModelClass.cast(determineTarget(getCurrentEvent()));

    if (targetModel != null) {
        if (List.class.isAssignableFrom(arg0.getClass())) {
            ret = processDropToTable(targetModel, arg0);
            getViewer().refresh();
        }
    }
    return ret;
}

public final boolean processDropToTable(TM targetModel, Object data) {

    List<TM> transferredModels = (List<TM>) data;
    List<TM> copyOfTransferredModels = transferredModels;

    switch (getCurrentOperation()) {
    case DND.DROP_COPY:
        copyOfTransferredModels = deepCopyBeanList(transferredModels, new String[]{});
        break;
    case DND.DROP_MOVE:
        // moving
        break;
    default:
        throw new UnsupportedOperationException(getCurrentOperation() + " is not supported!");
    }
    adjustPosition(transferredModels, copyOfTransferredModels, targetModel);

    return true;
}

private void adjustPosition(List<TM> transferredModels, List<TM> copyOfTransferredModels, TM targetModel) {
    int transferredObjectPosition = listOfModels.indexOf(transferredModels.get(0));
    listOfModels.removeAll(copyOfTransferredModels);
    addModelsToNewLocation(copyOfTransferredModels, targetModel, listOfModels, transferredObjectPosition);
    for (int i = 0; i < listOfModels.size(); i++) {
        int orderPosition = i * 10 + 10;
        listOfModels.get(i).setOrder(orderPosition);
    }
}

protected void addModelsToNewLocation(List<TM> transferredModels, TM targetModel, List<TM> targetList, int transferredObjectPosition) {
    switch (determineLocation(getCurrentEvent())) {
    case LOCATION_AFTER:
    case LOCATION_ON:
        int i;
        if (!transferredModels.contains(targetModel)) {
            i = targetList.indexOf(targetModel) + 1;
        } else {
            i = transferredObjectPosition;
        }
        targetList.addAll(i, transferredModels);
        break;
    case LOCATION_BEFORE:
        if (!transferredModels.contains(targetModel)) {
            i = targetList.indexOf(targetModel);
        } else {
            i = transferredObjectPosition;
        }
        targetList.addAll(i, transferredModels);

        break;
    case LOCATION_NONE:
    default:
        break;
    }
}

private List<TM> deepCopyBeanList(List<TM> transferredModels, String[] ignoreProperties) {
    List<TM> targetList = new LinkedList<TM>();

    for (TM element : transferredModels) {
        try {
            @SuppressWarnings("unchecked")
            TM copy = (TM) element.getClass().newInstance();
            BeanUtils.copyProperties(element, copy, ignoreProperties);
            targetList.add(copy);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    return targetList;
}

@Override
public boolean validateDrop(Object arg0, int arg1, TransferData arg2) {
    boolean ret = false;
    for (Transfer t : new Transfer[]{TaskTransfer.INSTANCE}) {
        if (t.isSupportedType(arg2)) {
            ret = true;
            break;
        }
    }
    return ret;
}
}

一个 DragSourceListener

public class MyDragSourceListener implements DragSourceListener {
private final Viewer dragSourceViewer;
private final boolean multiObjectsEnabled;
private final Class<?> transferrableElementClass;
private Object[] draggedObjects;

public MyDragSourceListener(Viewer dragSourceViewer, boolean multiObjectsEnabled, Class<?> transferrableElementClass) {
    this.dragSourceViewer = dragSourceViewer;
    this.multiObjectsEnabled = multiObjectsEnabled;
    this.transferrableElementClass = transferrableElementClass;
}

@Override
public void dragStart(DragSourceEvent event) {
    Control source = ((DragSource) event.getSource()).getControl();

    draggedObjects = null;

    if (dragSourceViewer.getControl().equals(source)) {
        if (multiObjectsEnabled) {
            draggedObjects = ((StructuredSelection) dragSourceViewer.getSelection()).toArray();
        } else {
            draggedObjects = new Object[]{((StructuredSelection) dragSourceViewer.getSelection()).getFirstElement()};
        }
    }
    event.doit = draggedObjects.length > 0 && transferredDataIsSupported();
}

private boolean transferredDataIsSupported() {
    boolean ret = true;
    for (Object o : draggedObjects) {
        if (o == null || !transferrableElementClass.isAssignableFrom(o.getClass())) {
            ret = false;
            break;
        }
    }
    return ret;
}

@Override
public void dragSetData(DragSourceEvent event) {
    event.data = Arrays.asList(draggedObjects);
}

@Override
public void dragFinished(DragSourceEvent event) {
    if (event.detail != DND.DROP_NONE) {
        dragSourceViewer.refresh();
    }
    draggedObjects = null;
}
}

在你的视图中放置一个类似这样的代码:

List<ITask> tasks = new WritableList(new ArrayList<ITask>(), ITask.class);

// Let's say tableViewerTasks is your TableViewer's name

DragSource sourceTasks = new DragSource(tblTasks, DND.DROP_MOVE);
sourceTasks.setTransfer(new Transfer[]{TaskTransfer.INSTANCE});
sourceTasks.addDragListener(new MyDragSourceListener(tableViewerTasks, true, ITask.class));

DropTarget targetTasks = new DropTarget(tblTasks, DND.DROP_MOVE);
targetTasks.setTransfer(new Transfer[]{TaskTransfer.INSTANCE});
targetTasks.addDropListener(new MyDropAdapter<ITask>(tableViewerTasks, ITask.class, tasks));

【讨论】:

  • 感谢您的回答。我可以使用LocalSelectionTransfer 而不是创建自己的传输类型吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-05
  • 2018-09-09
  • 1970-01-01
  • 2011-01-05
  • 2018-01-25
  • 2012-06-19
  • 2010-12-28
相关资源
最近更新 更多