文档

Java™ 教程
隐藏目录
演示 - ChooseDropAction
路径:使用Swing创建GUI
课程:拖放和数据传输
部分:选择拖放动作

演示 - 选择拖放动作

以下演示,ChooseDropActionDemo,包含三个列表。如屏幕截图所示,左侧的列表标有“从这里拖动”,是拖动源。此列表支持移动和复制,但不支持导入,因此您无法将数据放置在其中。

右侧有两个作为放置目标的列表。顶部的列表标有“复制到这里”,只允许将数据复制到其中。底部的列表标有“移动到这里”,只允许将数据移动到其中。源列表只允许从中拖动数据。

ChooseDropActionDemo演示的快照

请尝试: 
  1. 点击“启动”按钮以使用Java™ Web Start运行ChooseDropActionDemo下载JDK 7或更高版本)。或者,要自行编译和运行示例,请参阅示例索引启动ChooseDropActionDemo示例
  2. 在源列表中选择一个项目并将其拖动到上方的目标列表。当您拖动到目标位置时,请注意即使您没有按住Ctrl键表示要进行复制操作,复制放置的鼠标指针也会显示。(请注意,除非在Macintosh平台上按住Option键,否则不会显示复制指针。)
  3. 放置项目。它被插入到目标列表中,但未从源列表中移除,正如所期望的。
  4. 再次从源列表中拖动,这次拖动到下方的目标列表中。放置项目。它被插入到目标列表中并从源列表中移除。
  5. 在源列表中选择另一个项目,并同时按住Ctrl键以指示对复制操作的偏好,将项目拖动到下方的目标列表中。
  6. 将项目放置到列表中。项目不会被插入-放置被拒绝。传输处理器的canImport方法被编码为拒绝复制操作,但它也可以实现返回true,这样用户操作将占优势,复制将发生。

正如您可能猜到的,ChooseDropActionDemo.java示例包含两个TransferHandler实现:

/**
 * FromTransferHandler允许从列表中拖动,并支持复制和移动操作。此传输处理程序不支持导入。
 */
class FromTransferHandler extends TransferHandler {
    public int getSourceActions(JComponent comp) {
        return COPY_OR_MOVE;
    }

    private int index = 0;

    public Transferable createTransferable(JComponent comp) {
        index = dragFrom.getSelectedIndex();
        if (index < 0 || index >= from.getSize()) {
            return null;
        }

        return new StringSelection((String)dragFrom.getSelectedValue());
    }
    
    public void exportDone(JComponent comp, Transferable trans, int action) {
        if (action != MOVE) {
            return;
        }

        from.removeElementAt(index);
    }
}

/**
 * ToTransferHandler具有一个指定实例将仅支持复制操作还是移动操作的构造函数。此传输处理程序不支持导出。
 */
class ToTransferHandler extends TransferHandler {
    int action;
    
    public ToTransferHandler(int action) {
        this.action = action;
    }
    
    public boolean canImport(TransferHandler.TransferSupport support) {
        // 对于演示,我们只支持拖放(不支持剪贴板粘贴)
        if (!support.isDrop()) {
            return false;
        }

        // 我们只导入字符串
        if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            return false;
        }

        // 检查源操作是否包含所需操作 - 复制或移动,具体取决于创建此实例时指定的内容
        boolean actionSupported = (action & support.getSourceDropActions()) == action;
        if (actionSupported) {
            support.setDropAction(action);
            return true;
        }

        // 不支持所需操作,因此拒绝传输
        return false;
    }

    public boolean importData(TransferHandler.TransferSupport support) {
        // 如果我们无法处理导入,请说明
        if (!canImport(support)) {
            return false;
        }

        // 获取放置位置
        JList.DropLocation dl = (JList.DropLocation)support.getDropLocation();

        int index = dl.getIndex();

        // 获取数据并在失败时返回
        String data;
        try {
            data = (String)support.getTransferable().getTransferData(DataFlavor.stringFlavor);
        } catch (UnsupportedFlavorException e) {
            return false;
        } catch (java.io.IOException e) {
            return false;
        }

        JList list = (JList)support.getComponent();
        DefaultListModel model = (DefaultListModel)list.getModel();
        model.insertElementAt(data, index);

        Rectangle rect = list.getCellBounds(index, index);
        list.scrollRectToVisible(rect);
        list.setSelectedIndex(index);
        list.requestFocusInWindow();

        return true;
    }  
} 

源列表上附加的FromTransferHandler允许从列表中拖拽,并支持复制和移动操作。如果您尝试将其拖放到该列表上,拖放操作将被拒绝,因为FromTransferHandler没有实现canImportimportData方法。

附加到仅支持移动和仅支持复制的目标列表的ToTransferHandler包含一个指定目标列表是否仅允许复制或仅允许移动的构造函数。一个支持复制操作的实例附加到仅支持复制的列表上,而一个支持移动操作的实例附加到仅支持移动的列表上。

您可能还对顶级拖放示例感兴趣,该示例还演示了如何选择拖放操作。

接下来,我们将看一下如何显示拖放位置。


上一页:选择放置操作
下一页:显示放置位置