非文本组件中的 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("Cut");
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);
如果已为 CCP 操作设置了菜单加速器,则此下一步是多余的。如果尚未设置菜单加速器,则需要将 CCP 绑定添加到 ImportingMap。以下代码片段显示了如何完成此操作:
// only required if you have not set the menu accelerators
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
实例中实现 CCP。从屏幕快照中可以看到,有三个列表,您可以在任何一个列表中剪切,复制和粘贴。它们还支持拖放。对于此演示,粘贴的数据将在当前选择之后插入。如果没有当前选择,则将数据追加到列表的末尾。
Try this:
-
单击启动按钮以使用Java™Web 开始(下载 JDK 7 或更高版本)运行 ListCutPaste。另外,要自己编译和运行示例,请查阅example index。
-
在列表之一中选择一个项目。使用“编辑”菜单或等效的键盘从源中剪切或复制列表项。
-
选择要粘贴项 Object 列表项目。
-
使用菜单或等效的键盘粘贴文本。在当前选择之后粘贴该项目。
-
使用拖放执行相同的操作。