文档

Java™教程
隐藏目录
非文本组件中的CCP
路径:使用Swing创建GUI
课程:拖放和数据传输

非文本组件中的CCP

如果你正在使用 Swing 组件之一来实现剪切、复制和粘贴功能,而不是使用文本组件,你需要进行一些额外的设置。首先,你需要在操作映射中安装剪切、复制和粘贴操作。下面的方法展示了如何进行此设置:

    private void setMappings(JList list) { 
        ActionMap map = list.getActionMap();
        map.put(TransferHandler.getCutAction().getValue(Action.NAME),
                TransferHandler.getCutAction());
        map.put(TransferHandler.getCopyAction().getValue(Action.NAME),
                TransferHandler.getCopyAction());
        map.put(TransferHandler.getPasteAction().getValue(Action.NAME),
                TransferHandler.getPasteAction());

当设置编辑菜单时,你也可以选择添加菜单快捷键,这样用户就可以使用 Control-C 进行复制,例如。在下面的代码片段中,加粗的文本展示了如何为剪切操作设置菜单快捷键:

    menuItem = new JMenuItem("剪切");
    menuItem.setActionCommand((String)TransferHandler.getCutAction().
             getValue(Action.NAME));
    menuItem.addActionListener(actionListener);
    menuItem.setAccelerator(
      KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK));
    menuItem.setMnemonic(KeyEvent.VK_T);
    mainMenu.add(menuItem);

如果你已经为剪切、复制和粘贴操作设置了菜单快捷键,那么下一步就是多余的。如果你没有设置菜单快捷键,你需要将剪切、复制和粘贴操作绑定到输入映射中。下面的代码片段展示了如何完成这个操作:

    // 仅在没有设置菜单快捷键时才需要
    InputMap imap = this.getInputMap();
    imap.put(KeyStroke.getKeyStroke("ctrl X"),
        TransferHandler.getCutAction().getValue(Action.NAME));
    imap.put(KeyStroke.getKeyStroke("ctrl C"),
        TransferHandler.getCopyAction().getValue(Action.NAME));
    imap.put(KeyStroke.getKeyStroke("ctrl V"),
        TransferHandler.getPasteAction().getValue(Action.NAME));

一旦绑定安装完毕并设置了编辑菜单,还有一个问题需要解决:当用户进行剪切、复制或粘贴操作时,哪个组件应该接收该操作?对于文本组件,DefaultEditorKit 会记住上次拥有焦点的组件,并将操作转发给该组件。下面的 TransferActionListener 类为非文本的 Swing 组件执行相同的功能。这个类可以在大多数应用程序中使用:

public class TransferActionListener implements ActionListener,
                                              PropertyChangeListener {
    private JComponent focusOwner = null;

    public TransferActionListener() {
        KeyboardFocusManager manager = KeyboardFocusManager.
           getCurrentKeyboardFocusManager();
        manager.addPropertyChangeListener("permanentFocusOwner", this);
    }

    public void propertyChange(PropertyChangeEvent e) {
        Object o = e.getNewValue();
        if (o instanceof JComponent) {
            focusOwner = (JComponent)o;
        } else {
            focusOwner = null;
        }
    }

    public void actionPerformed(ActionEvent e) {
        if (focusOwner == null)
            return;
        String action = (String)e.getActionCommand();
        Action a = focusOwner.getActionMap().get(action);
        if (a != null) {
            a.actionPerformed(new ActionEvent(focusOwner,
                                              ActionEvent.ACTION_PERFORMED,
                                              null));
        }
    }
}

最后,您需要决定如何处理粘贴操作。对于拖放操作,您将数据插入到放置位置。对于粘贴操作,您无法确定用户所需粘贴的位置。您需要决定对您的应用程序来说什么是合理的解决方案 - 在当前选择之前还是之后插入数据可能是最好的解决方案。

下面的演示示例ListCutPaste展示了如何在JList实例中实现剪切、复制和粘贴功能。如屏幕截图所示,有三个列表,您可以在这些列表之间进行剪切、复制和粘贴操作。它们还支持拖放操作。对于此演示,粘贴的数据将插入到当前选择之后。如果没有当前选择,数据将追加到列表的末尾。

ListCutPaste示例的快照。

请尝试以下操作: 
  1. 点击“Launch”按钮使用Java™ Web Start运行ListCutPaste示例(下载JDK 7或更高版本)。或者,如果您想自己编译和运行示例,请参考示例索引启动ListCutPaste示例
  2. 在其中一个列表中选择一个项目。使用编辑菜单或键盘快捷键将列表项剪切或复制。
  3. 选择要粘贴项目的列表项。
  4. 使用菜单或键盘快捷键粘贴文本。项目将在当前选择之后粘贴。
  5. 使用拖放操作执行相同的操作。


上一页: 文本组件中的CCP
下一页: 使用和创建DataFlavor