【问题标题】:Detect CTRL+V in Swing App but keep original function在 Swing App 中检测 CTRL+V 但保留原始功能
【发布时间】:2015-05-21 19:40:20
【问题描述】:

编写一个聊天应用程序,我希望用户能够从他/她的剪贴板中发送图像。为此,我想捕捉任何CTRL+Vkeyboard 输入。由于默认情况下应该可以粘贴文本,因此必须覆盖原始 ctrl+v 功能(粘贴文本)。

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

第一个:取自official Java documentation:KEY LISTENER

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!
    }
});

有什么想法吗?

注意:我使用的是“外国”键盘布局(德语)。但我不明白为什么这会产生任何影响 - 我非常希望我的应用程序能够在国际范围内工作。

干杯

编辑。 Alt+SomeKey 但是被 KeyListener 正确识别

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

【问题讨论】:

  • 还没有测试过,很久没写swing代码了,但是一件事就是尝试做aMap.get来获取当前的处理程序。如果这可行,那么您的新处理程序可以委托并执行额外的处理。只是一个想法......

标签: java swing keylistener key-bindings ctrl


【解决方案1】:

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

这里的解决方案很简单。您可以通过添加一个CombinedAction 类来简单地自行组合这些操作,该类将执行绑定到CTRL+V 的“原始”操作和您要执行的“自定义”操作。

请参阅下面结合两个操作的小示例(这里我的自定义操作是 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();
                }
            }
        });
    }

}

【讨论】:

  • 感谢您的意见,它有效!然而,Javadoc 说 registerKeyboardAction 已过时。为什么选择不使用InputMap?是因为getActionForKeyStroke 只为ActionListeners 工作吗?所以这个确切的问题是我不能使用Input/OutputMap-System 的唯一时间,尽管 Java 鼓励我这样做?
  • @Blauhirn 据我记得,registerKeyboardAction 只是操作组件的 ActionMap/InputMap 的快捷方式。我不确定为什么 Javadoc 声明它已过时,但修改我上面的代码以使用 ActionMap/InputMap 而不是这种方法应该是微不足道的。
  • 好事解决总是微不足道的。
  • 进一步研究:如果有人试图将其转换为使用 AM/IM,您必须使 CombinedAction 扩展 AbstractAction 而不是实现 ActionListener。现在可以运行了。
猜你喜欢
  • 2020-04-06
  • 2014-09-27
  • 2011-10-13
  • 1970-01-01
  • 2011-02-26
  • 2017-07-31
  • 1970-01-01
  • 2011-02-23
相关资源
最近更新 更多