在 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();
}
}
});
}
}
在编写聊天应用程序时,我希望用户能够从 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();
}
}
});
}
}