java 键绑定 - 不要在 windows 中捕获 AltGr 的 CTRL

java key-bindings - don't catch the CTRL of AltGr in windows

在 java 键绑定中,在 windows 中,我如何识别何时按下 CTRL 键本身,而不是在按下 AltGr 键时?

我的进程处理必须由CTRL键本身启动,而且我还需要知道CTRL键什么时候被释放。

瑞士/德国法国用户出现问题:要键入“@”,他们必须同时按下 "AltGr" + “2”。 在这种情况下,windows 将 AltGr 转换为 ALT + CTRL 并且我的进程启动错误。

我指出我想使用键绑定。

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class MyCtrl extends JFrame {

void init() {

    JPanel panel = new JPanel();
    setContentPane(panel);

    InputMap inputMap = panel.getInputMap();
    ActionMap actionMap = panel.getActionMap();

    /**
     * action for CTRL
     */
    KeyStroke controlKey = KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, InputEvent.CTRL_MASK);
    inputMap.put(controlKey, "ctrl");
    actionMap.put("ctrl", new CtrlAction());

    /**
     * action for release CTRL
     */
    KeyStroke releaseControlKey = KeyStroke.getKeyStroke("released CONTROL");
    inputMap.put(releaseControlKey, "release ctrl");
    actionMap.put("release ctrl", new ReleaseCtrlAction());
}

public class CtrlAction extends AbstractAction {

    @Override
    public void actionPerformed(ActionEvent e) {
        if(AltGr is pressed)
           {// do nothing}
        else
           System.out.println("control");
    }
}

public class ReleaseCtrlAction extends AbstractAction {

    @Override
    public void actionPerformed(ActionEvent e) {
        if(AltGr is pressed)
           {// do nothing}
        else
           System.out.println("release control");
    }
}

/**
 * main
 */
public static void main(String[] a) {
    MyCtrl myProjet = new MyCtrl();
    myProjet.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    myProjet.setPreferredSize(new Dimension(200, 100));
    myProjet.init();
    myProjet.pack();
    myProjet.setVisible(true);
}

}

我可以想到两个解决方案:

  1. 而不是使用面板的 input/action 映射 - 在 KeyListener() 中处理操作。这似乎是一个直接的解决方案。

  2. 将 ALT 键处理添加到 input/action 映射,并在处理程序中保留一个可以在控制处理程序中检查的标志。

不过我更喜欢 (1)。

谢谢 KDM。正如我解释的那样,我想使用键绑定,所以我先尝试了你的第二个想法。但是我在按下 AltGr 时无法捕获 window 启动的 ALT 修改器。
所以我选择了第一个解决方案,假设测试 ALT/CTRL 修饰符是一种不容易使用键绑定处理的特殊情况。
另见 here。 非常欢迎改进/建议。

import java.awt.Dimension;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MyCtrl3 extends JFrame {

private class MyDispatcher implements KeyEventDispatcher {
    // usualy one prefer using keybindings - but we are in
    // special case for detect AltGr
    @Override
    public boolean dispatchKeyEvent(KeyEvent e) {
        if (e.getID() == KeyEvent.KEY_PRESSED) {
            if (e.isAltGraphDown()) {
                // uncaught in windows
                System.out.println("ALT GRAPH");
            } else if (e.isControlDown()) {
                // fired 1 by windows when press AltGr
                System.out.println("CONTROL");
                // here I launch a timer, 1ms delay is enough 
                // to wait for ALT key if coming
            } else if (e.isAltDown()) {
                // fired 2 by windows when press AltGr
                // here I unarm the timer
                System.out.println("ALT");
            }
        } else if (e.getID() == KeyEvent.KEY_RELEASED) {
            if (e.getKeyCode() == KeyEvent.VK_ALT_GRAPH) {
                System.out.println("ALT GRAPH released");
            } else if (e.getKeyCode() == KeyEvent.VK_ALT) {
                System.out.println("ALT released");
            } else if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
                System.out.println("CONTROL released");
            }
        }
        return false;
    }
}

public MyCtrl3() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setPreferredSize(new Dimension(200, 100));
    KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
    manager.addKeyEventDispatcher(new MyDispatcher());
}

public static void main(String[] a) {
    MyCtrl3 myProjet = new MyCtrl3();
    myProjet.pack();
    myProjet.setVisible(true);
}
}