如何以编程方式确定不同键盘布局上“Ctrl + Plus”和“Ctrl + Minus”的正确击键?

问题描述

我正在尝试绑定 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);
    }
  }
}

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

enter image description here

解决方法

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

作为替代方案,您可以监听所有 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 + "-" 不会生成有效的键字符。

所以我的下一次尝试是尝试使用 Robot 使用不同的按键来查看生成的字符:

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:

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 答案的修改版本。

+- 位于

的键盘布局上
  • 主层,它同时触发 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");
          }
        }
      }
    });
  }
}