【问题标题】:How to programmatically determine the correct keystroke for "Ctrl + Plus" and "Ctrl + Minus" on different keyboard layouts?如何以编程方式确定不同键盘布局上“Ctrl + Plus”和“Ctrl + Minus”的正确击键?
【发布时间】:2021-04-11 12:21:44
【问题描述】:

我正在尝试绑定 Ctrl + +Ctrl + - 来放大/缩小动作.

question 解释说,在某些键盘布局中,+- 存在于主要层上,而在其他键盘布局中,它们存在于次要层上(您必须按 Shift 之类的修饰键键入)。另请参阅错误 42620446942481

目前看来我必须分析我想要支持的所有布局,并根据当前布局配置不同的按键绑定,例如:

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

有没有办法为所有(或大多数)布局以编程方式为+- 找出正确的击键?

【问题讨论】:

    标签: java swing keyboard-shortcuts keyboard-events keyboard-layout


    【解决方案1】:

    这包括通过任何方式键入“加号”,包括按下 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);
                }
            }
        }
    });
    

    【讨论】:

    • 谢谢。从技术上讲不是问题的答案,但它确实解决了我的问题。所以在有人弄清楚标题中的问题之前,我会接受这个。
    【解决方案2】:

    我不知道如何使用键绑定。

    作为替代方案,您可以侦听所有 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("-"));
        }
    }
    

    但是这种方法存在时间问题。我尝试在各个步骤中添加延迟,这看起来确实很有帮助。

    这两种方法都不能解决您的问题,但它可能会给您一些想法?

    【讨论】:

    • 谢谢。减号一定是一个非常奇怪的键。结合 Ctrl 或 Ctrl + Shift 生成有趣或无 keyChar。只需按 Ctrl,它甚至会在瑞士德语布局上生成一个 TYPED 事件(但不是在美国布局上)。 ?‍♂️
    【解决方案3】:

    我最终选择了 thgw 答案的修改版本。

    +- 位于的键盘布局上

    • primary layer,它同时触发CtrlCtrl + 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");
              }
            }
          }
        });
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-18
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      • 1970-01-01
      相关资源
      最近更新 更多