在 Swing App 中检测 CTRL+V 但保留原始功能

Detect CTRL+V in Swing App but keep original function

在编写聊天应用程序时,我希望用户能够从 his/her 剪贴板发送图像。为此,我想捕获任何 CTRL+V 键盘输入。由于默认情况下应该可以粘贴文本,因此必须而不是覆盖原始的 ctrl+v 功能(粘贴文本)。

我看到有两种方法,其中 none 适合我:

1st:摘自official Java documentation:关键监听器

editorPane.addKeyListener(new KeyListener() {
    @Override
    public void keyPressed(KeyEvent e) {
        e.getKeyChar()
        // when I press ctrl+v, ^ this is falsely a white square character, looks like (U+25A1). Plain v without ctrl does work.
        e.getKeyCode()
        // ^ this is falsely 0

        // (e.getModifiersEx() correctly returns InputEvent.CTRL_DOWN_MASK)
    }

第二:按键绑定

InputMap iMap = editorPane.getInputMap(condition);
ActionMap aMap = editorPane.getActionMap();
iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK), "ctrlV");
aMap.put("ctrlV", new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // works, but overrides natural ctrl+v function!
    }
});

有什么想法吗?

注意:我使用的是 "foreign" 键盘布局(德语)。但我不明白为什么这会有什么不同 - 我非常希望我的应用程序可以在国际上使用。

干杯

编辑。 Alt+SomeKey 但是被 KeyListener

正确识别

编辑2。将键盘布局更改为美国后,问题仍然存在。

坚持使用键绑定:KeyListener 是一种低级 API,而键绑定将为您提供一致、可预测和稳健的行为。

这里的解决方法很简单。您可以通过添加 CombinedAction class 来简单地自己组合操作,这将执行绑定到 CTRL+V 的 "original" 操作和您要执行的 "custom" 操作。

请参阅下面结合这两个操作的小示例(此处我的自定义操作是 Sysout):

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;

public class TestEditorPane {
    private JEditorPane editorPane;

    public static class CombinedAction implements ActionListener {
        private final ActionListener action1;
        private final ActionListener action2;

        public CombinedAction(ActionListener action1, ActionListener action2) {
            super();
            this.action1 = action1;
            this.action2 = action2;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (action1 != null) {
                action1.actionPerformed(e);
            }
            if (action2 != null) {
                action2.actionPerformed(e);
            }
        }

    }

    public TestEditorPane() {
    }

    private void initUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // JTEXTBOX
        editorPane = new JEditorPane();
        KeyStroke ctrlV = KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_DOWN_MASK);
        final ActionListener ctrlVAction = editorPane.getActionForKeyStroke(ctrlV);
        editorPane.registerKeyboardAction(new CombinedAction(ctrlVAction, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("This is my action on CTRL+V");
            }
        }), ctrlV, JComponent.WHEN_FOCUSED);
        // JSCROLLPANE
        JScrollPane scroll1 = new JScrollPane(editorPane);
        scroll1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scroll1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        frame.add(scroll1);
        frame.setSize(400, 400);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    TestEditorPane test = new TestEditorPane();
                    test.initUI();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

}