如何以编程方式确定 "Ctrl + Plus" 和 "Ctrl + Minus" 在不同键盘布局上的正确击键?
How to programmatically determine the correct keystroke for "Ctrl + Plus" and "Ctrl + Minus" on different keyboard layouts?
我正在尝试绑定 Ctrl + + 和 Ctrl + - 放大/缩小动作。
这个question explains that on some keyboard layouts, + and - exist on the primary layer, whereas on others they exist on the secondary layer (you have to press a modifier key like Shift to type it). Also see bugs 4262044 and 6942481.
目前看来我必须分析我想要支持的所有布局,并根据当前布局配置不同的击键绑定,例如:
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;
public class KeyStrokeTest extends JFrame {
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame();
// en_US
register(frame, "control shift EQUALS");
register(frame, "control MINUS");
// de_DE
// register(frame, "control PLUS");
// register(frame, "control MINUS");
// de_CH
// register(frame, "control shift 1");
// register(frame, "control MINUS");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.getRootPane().setFocusable(true);
frame.getRootPane().requestFocusInWindow();
}
private static void register(JFrame frame, String keyStrokeDefinition) {
KeyStroke keyStroke = KeyStroke.getKeyStroke(keyStrokeDefinition);
String key = keyStrokeDefinition;
frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, key);
frame.getRootPane().getActionMap().put(key, new TestAction(keyStrokeDefinition));
}
private static class TestAction extends AbstractAction {
private String info;
public TestAction(String info) {
this.info = info;
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Action performed: " + info);
}
}
}
有没有办法以编程方式找出所有(或大多数)布局的 +
和 -
的正确击键?
我不知道如何使用键绑定。
作为替代方案,您可以监听所有 KeyEvent 并处理您的具体情况:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class Control implements AWTEventListener
{
private boolean isPressed;
public Control()
{
long eventMask = AWTEvent.KEY_EVENT_MASK;
Toolkit.getDefaultToolkit().addAWTEventListener( this , eventMask);
}
public void eventDispatched(AWTEvent e)
{
KeyEvent ke = (KeyEvent)e;
if (ke.getKeyCode() == KeyEvent.VK_CONTROL)
isPressed = e.getID() == KeyEvent.KEY_PRESSED;
if (isPressed
&& e.getID() == KeyEvent.KEY_PRESSED
&& ke.getKeyChar() == '+')
System.out.println("Zoom In");
}
private static void createAndShowGUI()
{
new Control();
JTextField textField = new JTextField(20);
textField.setFont( textField.getFont().deriveFont(24.0f) );
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( textField );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
但是,它只对“+”有效,对“-”无效。出于某种原因,Ctrl + "-" 不会生成有效的键字符。
所以我的下一次尝试是尝试使用机器人使用不同的按键来查看生成的字符:
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.lang.reflect.*;
public class KeyboardMap
{
private HashMap<String, KeyStroke> keyStrokes = new HashMap<>();
private JTextField textField = new JTextField(10);
private Robot robot;
public KeyboardMap()
{
// Create dummy dialog for usage by the Robot
JDialog dialog = new JDialog();
// dialog.setLocation(-200, -200);
dialog.add( textField );
dialog.pack();
dialog.setVisible(true);
try
{
robot = new Robot();
robot.delay(32);
ArrayList<Integer> keyCodes = getKeyCodes();
for (Integer keyCode: keyCodes)
{
System.out.println(keyCode);
generateCharacter(keyCode, false);
generateCharacter(keyCode, true);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
private ArrayList<Integer> getKeyCodes() throws Exception
{
ArrayList<Integer> keyCodes = new ArrayList<>();
keyCodes.add( KeyEvent.VK_0 );
keyCodes.add( KeyEvent.VK_1 );
keyCodes.add( KeyEvent.VK_2 );
keyCodes.add( KeyEvent.VK_3 );
keyCodes.add( KeyEvent.VK_4 );
keyCodes.add( KeyEvent.VK_5 );
keyCodes.add( KeyEvent.VK_6 );
keyCodes.add( KeyEvent.VK_7 );
keyCodes.add( KeyEvent.VK_8 );
keyCodes.add( KeyEvent.VK_9 );
// keyCodes.add( KeyEvent.VK_PLUS );
// keyCodes.add( KeyEvent.VK_ADD );
keyCodes.add( KeyEvent.VK_EQUALS );
keyCodes.add( KeyEvent.VK_MINUS );
return keyCodes;
}
private ArrayList<Integer> getKeyCodes2() throws Exception
{
ArrayList<Integer> keyCodes = new ArrayList<>();
Field[] fields = KeyEvent.class.getFields();
for (Field field: fields)
{
if (field.getName().startsWith("VK_"))
{
int keyCode = field.getInt(null);
System.out.println(keyCode + " : " + field.getName());
// if (keyCode < 1000)
if (field.getName().length() == 4)
{
keyCodes.add( keyCode );
// System.out.println(field.getName());
}
}
}
return keyCodes;
}
private void generateCharacter(int keyCode, boolean useShift)
{
if (useShift) robot.keyPress( KeyEvent.VK_SHIFT );
robot.keyPress( keyCode );
robot.keyRelease( keyCode );
if (useShift) robot.keyRelease( KeyEvent.VK_SHIFT );
robot.delay(50);
String text = textField.getText();
// System.out.println(keyCode + " : " + useShift + " : " + text);
textField.setText("");
if (text.length() == 1)
{
int modifier = (useShift) ? KeyEvent.SHIFT_DOWN_MASK : 0;
KeyStroke ks = KeyStroke.getKeyStroke(keyCode, modifier);
keyStrokes.put(text, ks);
}
}
public KeyStroke getKeyStroke(String character)
{
return keyStrokes.get(character);
}
public static void main(String[] args) throws Exception
{
KeyboardMap map = new KeyboardMap();
System.out.println(map.getKeyStroke("0"));
System.out.println(map.getKeyStroke(")"));
System.out.println(map.getKeyStroke("1"));
System.out.println(map.getKeyStroke("!"));
System.out.println(map.getKeyStroke("+"));
System.out.println(map.getKeyStroke("-"));
}
}
但是这种方法存在时间问题。我尝试在各个步骤中添加延迟,这似乎很有帮助。
这两种方法都不能解决您的问题,但它可能会给您一些想法?
这包括通过任何方式键入 'plus',包括按下 CTRL 或 CTRL SHIFT:
register(f, "control MINUS");
register(f, "control SUBTRACT"); // minus on the numpad
// this covers typing a 'plus' by any means which include pressing down CTRL or CTRL SHIFT
f.getRootPane().addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent evt) {
String name = "control (shift) +";
int mods = evt.getModifiersEx();
if (mods == KeyEvent.CTRL_DOWN_MASK
|| mods == (KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)) {
if (evt.getKeyChar() == '+') {
System.out.println("Action performed: " + name);
}
}
}
});
我最终采用了 thgw 答案的修改版本。
在 + 或 - 位于
的键盘布局上
初级层,Ctrl和Ctrl + Shift.
都会触发
次要(Shift)层,仅在Ctrl + Shift.
时触发
也适用于小键盘加减键。
import java.awt.event.*;
import javax.swing.*;
public class Test {
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getModifiersEx() == InputEvent.CTRL_DOWN_MASK //
|| e.getModifiersEx() == (InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)) {
if(e.getKeyChar() == '+' || e.getKeyCode() == KeyEvent.VK_PLUS) {
System.out.println("zoom in");
}
if(e.getKeyChar() == '-' || e.getKeyCode() == KeyEvent.VK_MINUS) {
System.out.println("zoom out");
}
}
}
});
}
}
我正在尝试绑定 Ctrl + + 和 Ctrl + - 放大/缩小动作。
这个question explains that on some keyboard layouts, + and - exist on the primary layer, whereas on others they exist on the secondary layer (you have to press a modifier key like Shift to type it). Also see bugs 4262044 and 6942481.
目前看来我必须分析我想要支持的所有布局,并根据当前布局配置不同的击键绑定,例如:
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;
public class KeyStrokeTest extends JFrame {
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame();
// en_US
register(frame, "control shift EQUALS");
register(frame, "control MINUS");
// de_DE
// register(frame, "control PLUS");
// register(frame, "control MINUS");
// de_CH
// register(frame, "control shift 1");
// register(frame, "control MINUS");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.getRootPane().setFocusable(true);
frame.getRootPane().requestFocusInWindow();
}
private static void register(JFrame frame, String keyStrokeDefinition) {
KeyStroke keyStroke = KeyStroke.getKeyStroke(keyStrokeDefinition);
String key = keyStrokeDefinition;
frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, key);
frame.getRootPane().getActionMap().put(key, new TestAction(keyStrokeDefinition));
}
private static class TestAction extends AbstractAction {
private String info;
public TestAction(String info) {
this.info = info;
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Action performed: " + info);
}
}
}
有没有办法以编程方式找出所有(或大多数)布局的 +
和 -
的正确击键?
我不知道如何使用键绑定。
作为替代方案,您可以监听所有 KeyEvent 并处理您的具体情况:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class Control implements AWTEventListener
{
private boolean isPressed;
public Control()
{
long eventMask = AWTEvent.KEY_EVENT_MASK;
Toolkit.getDefaultToolkit().addAWTEventListener( this , eventMask);
}
public void eventDispatched(AWTEvent e)
{
KeyEvent ke = (KeyEvent)e;
if (ke.getKeyCode() == KeyEvent.VK_CONTROL)
isPressed = e.getID() == KeyEvent.KEY_PRESSED;
if (isPressed
&& e.getID() == KeyEvent.KEY_PRESSED
&& ke.getKeyChar() == '+')
System.out.println("Zoom In");
}
private static void createAndShowGUI()
{
new Control();
JTextField textField = new JTextField(20);
textField.setFont( textField.getFont().deriveFont(24.0f) );
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( textField );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
但是,它只对“+”有效,对“-”无效。出于某种原因,Ctrl + "-" 不会生成有效的键字符。
所以我的下一次尝试是尝试使用机器人使用不同的按键来查看生成的字符:
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.lang.reflect.*;
public class KeyboardMap
{
private HashMap<String, KeyStroke> keyStrokes = new HashMap<>();
private JTextField textField = new JTextField(10);
private Robot robot;
public KeyboardMap()
{
// Create dummy dialog for usage by the Robot
JDialog dialog = new JDialog();
// dialog.setLocation(-200, -200);
dialog.add( textField );
dialog.pack();
dialog.setVisible(true);
try
{
robot = new Robot();
robot.delay(32);
ArrayList<Integer> keyCodes = getKeyCodes();
for (Integer keyCode: keyCodes)
{
System.out.println(keyCode);
generateCharacter(keyCode, false);
generateCharacter(keyCode, true);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
private ArrayList<Integer> getKeyCodes() throws Exception
{
ArrayList<Integer> keyCodes = new ArrayList<>();
keyCodes.add( KeyEvent.VK_0 );
keyCodes.add( KeyEvent.VK_1 );
keyCodes.add( KeyEvent.VK_2 );
keyCodes.add( KeyEvent.VK_3 );
keyCodes.add( KeyEvent.VK_4 );
keyCodes.add( KeyEvent.VK_5 );
keyCodes.add( KeyEvent.VK_6 );
keyCodes.add( KeyEvent.VK_7 );
keyCodes.add( KeyEvent.VK_8 );
keyCodes.add( KeyEvent.VK_9 );
// keyCodes.add( KeyEvent.VK_PLUS );
// keyCodes.add( KeyEvent.VK_ADD );
keyCodes.add( KeyEvent.VK_EQUALS );
keyCodes.add( KeyEvent.VK_MINUS );
return keyCodes;
}
private ArrayList<Integer> getKeyCodes2() throws Exception
{
ArrayList<Integer> keyCodes = new ArrayList<>();
Field[] fields = KeyEvent.class.getFields();
for (Field field: fields)
{
if (field.getName().startsWith("VK_"))
{
int keyCode = field.getInt(null);
System.out.println(keyCode + " : " + field.getName());
// if (keyCode < 1000)
if (field.getName().length() == 4)
{
keyCodes.add( keyCode );
// System.out.println(field.getName());
}
}
}
return keyCodes;
}
private void generateCharacter(int keyCode, boolean useShift)
{
if (useShift) robot.keyPress( KeyEvent.VK_SHIFT );
robot.keyPress( keyCode );
robot.keyRelease( keyCode );
if (useShift) robot.keyRelease( KeyEvent.VK_SHIFT );
robot.delay(50);
String text = textField.getText();
// System.out.println(keyCode + " : " + useShift + " : " + text);
textField.setText("");
if (text.length() == 1)
{
int modifier = (useShift) ? KeyEvent.SHIFT_DOWN_MASK : 0;
KeyStroke ks = KeyStroke.getKeyStroke(keyCode, modifier);
keyStrokes.put(text, ks);
}
}
public KeyStroke getKeyStroke(String character)
{
return keyStrokes.get(character);
}
public static void main(String[] args) throws Exception
{
KeyboardMap map = new KeyboardMap();
System.out.println(map.getKeyStroke("0"));
System.out.println(map.getKeyStroke(")"));
System.out.println(map.getKeyStroke("1"));
System.out.println(map.getKeyStroke("!"));
System.out.println(map.getKeyStroke("+"));
System.out.println(map.getKeyStroke("-"));
}
}
但是这种方法存在时间问题。我尝试在各个步骤中添加延迟,这似乎很有帮助。
这两种方法都不能解决您的问题,但它可能会给您一些想法?
这包括通过任何方式键入 'plus',包括按下 CTRL 或 CTRL SHIFT:
register(f, "control MINUS");
register(f, "control SUBTRACT"); // minus on the numpad
// this covers typing a 'plus' by any means which include pressing down CTRL or CTRL SHIFT
f.getRootPane().addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent evt) {
String name = "control (shift) +";
int mods = evt.getModifiersEx();
if (mods == KeyEvent.CTRL_DOWN_MASK
|| mods == (KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)) {
if (evt.getKeyChar() == '+') {
System.out.println("Action performed: " + name);
}
}
}
});
我最终采用了 thgw 答案的修改版本。
在 + 或 - 位于
的键盘布局上初级层,Ctrl和Ctrl + Shift.
都会触发次要(Shift)层,仅在Ctrl + Shift.
时触发
也适用于小键盘加减键。
import java.awt.event.*;
import javax.swing.*;
public class Test {
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getModifiersEx() == InputEvent.CTRL_DOWN_MASK //
|| e.getModifiersEx() == (InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)) {
if(e.getKeyChar() == '+' || e.getKeyCode() == KeyEvent.VK_PLUS) {
System.out.println("zoom in");
}
if(e.getKeyChar() == '-' || e.getKeyCode() == KeyEvent.VK_MINUS) {
System.out.println("zoom out");
}
}
}
});
}
}