KeyListener 如何检测组合键(例如,ALT + 1 + 1)

Posted

技术标签:

【中文标题】KeyListener 如何检测组合键(例如,ALT + 1 + 1)【英文标题】:How can a KeyListener detect key combinations (e.g., ALT + 1 + 1) 【发布时间】:2011-12-12 16:24:43 【问题描述】:

如何让我的自定义 KeyListener 侦听 ALT(或 CTRL 就此而言)+多个其他键的组合?

假设我希望应用程序执行 11 种不同的操作,具体取决于按下的按键组合。 ALT + 0 - ALT + 9 显然不会造成任何问题,而对于 ALT + 1 + 0(或“ALT+10”,因为它可以在帮助文件或类似文件中描述)我在网络上的任何地方都找不到好的解决方案(或在我的脑海中)。我不相信this solution with a timer 是唯一可能的方法。

提前一百万感谢您的任何建议!

编辑: 动作 0-9 + 动作 10 = 11 个动作。谢谢@X-Zero。

【问题讨论】:

ALT10 实际上是第 11 个动作...我通常也会尽量避免 需要 两只 手按的东西(因为 1 和 0 通常位于键盘的两端) - 请尝试使用不同的/附加的修饰键。此外,如果您尝试添加另一个热键,则无法使用 ALT11... @X-Zero:对不起,你是对的,这将是第 11 次行动 :)。我为什么要这样做是因为将在表中具有ints 标题的列上调用这些操作。因此,例如,如果用户想要更改第 11 列(将被称为“10”)中的数据,他/她会按 ALT + 1 + [让 ALT1 都离开] 0。除了使用 ALT 键之外,我还可以想象使用另一个键,例如 Shift 或类似键。 你最好分配一个热键来弹出一个列选择对话框,用户可以输入列索引或名称(名称比仅索引更好)。这应该更容易实现,并且对用户来说更容易。除此之外,您如何判断用户想要更改第 11 列,而不是在第 1 列中添加 1?并且不要显示以 0 开头的列号,因为这只会让不习惯使用基于 0 的数组的人感到困惑。 有关用户可能期望发布或多步热键如何工作的示例,请查看 Eclipse 如何嵌套对话框。具体来说,按键释放会弹出初始对话框,然后进一步按键激活该对话框上的对象。您的用户可能会期望这种行为,而不是转向“基于十位”的热键方法(当您到达第 100 列时会发生什么?)。此外,请做好准备,尽管您的热键很有用,但您的用户永远找不到或(可能拒绝)采用热键。 嗨@X-Zero:该应用程序有一个高度特定的用户群,他们习惯于使用数组(实际上他们知道他们正在处理一个数组),因此我不认为该列没有.s 以 0 开头是一个问题。我想绕过触发另一个弹出对话框的弹出对话框,并且由于速度至关重要,用户应该能够输入ALT + 1 + 1(或ALT + 1 + 1 + 1),然后弹出窗口似乎会更新另一个中的数据表中的行。 ALT + X 组合键是为应用程序中的“调用列”保留的,所以我不必担心“交叉使用”。 【参考方案1】:

我认为我正在使用一种更简单的方法。如果 KeyEvent 是 ev,那么如果您进行调查:

(int)ev.getKeyChar()

你发现 ctrl-a 为 1,ctrl-b 为 2,以此类推。我想使用 ctrl-s 进行保存。所以我只是使用:

(((int)ev.getKeyChar())==19)

检测它。不知道为什么,但它工作正常,而:

ev.isControlDown() && ev.getKeyChar()=='s'

没有。

【讨论】:

【参考方案2】:

我建议不要使用组合键,而是在窗口 isVisible() 被聚焦时考虑一些输入字段。该字段可以是隐藏的,如 Windows 的文件资源管理器隐藏文件名搜索(输入目录,键入文件名和对应的焦点),或者是可见的,如在 Ubuntu 中。

组合键的设计目的是包含除修饰符之外的多个键,尽管您可能能够实现这一点。

【讨论】:

【参考方案3】:
import java.awt.*;
import java.awt.event.*;
class KDemo

     public static void main(String args[])
     
           Frame f = new Frame();
           f.setSize(500,500);
           f.setVisible(true);
           f.addKeyListener(new KeyAdapter()
           
               public void keyPressed(KeyEvent e)
               
                   AWTKeyStroke ak = AWTKeyStroke.getAWTKeyStrokeForEvent(e);
                   if(ak.equals(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_F4,InputEvent.ALT_MASK)))
                   
                     System.exit(0);
                   
               
           );
        
   

【讨论】:

【参考方案4】:

ALT + 1 + 0(或“ALT+10”,因为它可以在帮助文件或类似文件中描述)

似乎与(来自您的一个 cmets)发生冲突:

例如,如果用户想要更改第 11 列(称为“10”)中的数据,她/他会按 ALT + 1 + [同时松开 ALT 和 1] 0。

假设 ALT+10 表示“按下 ALT,按下并释放 1,按下并释放 0,释放 ALT”我建议尝试以下操作:

在 keyPressed 中,监听 ALT 键,激活一个布尔标志 isAltPressed,并创建一个缓冲区来保存发生的按键操作(例如,一个字符串)。 在 keyTyped 中,如果 isAltPressed 处于活动状态,则将键代码附加到缓冲区。 在keyReleased中,再次监听ALT,打开条件查询缓冲区并执行动作。

    public void keyPressed (KeyEvent e)
        if (e.getKeyCode() == KeyEvent.VK_ALT)
        buffer = ""; //declared globally
        isAltPressed = true;  //declared globally
    

    public void keyTyped (KeyEvent e)
        if (isAltPressed)
            buffer.append (e.getKeyChar());
    

    public void keyReleased (KeyEvent e)
        if (e.getKeyCode() == KeyEvent.VK_ALT)
            isAltPressed = false;
            if (buffer.equals (4948)) //for pressing "1" and then "0"
                doAction();
            else if (buffer.equals(...))
                doOtherAction();
            ...
        //if alt
    

【讨论】:

【参考方案5】:

你可以通过组合某些东西来使用KeyListener。看下面的例子,应该放在一个被覆盖的keyPressed(KeyEvent e)方法中。

if (e.isControlDown() && e.getKeyChar() != 'a' && e.getKeyCode() == 65) 
        System.out.println("Select All"); 

Ctrl + a 时将显示字符串Select Alle.isControlDown() 方法检查是否按下了 Ctrl 键。 类似地,Alt 组合键可以使用e.isAltDown() 方法以相同的方法完成。

这背后的逻辑是,e.getKeyChar() 返回按键的字符,e.getKeyCode() 返回其 ASCII 码。当 Ctrl 被按住时,e.getKeyChar() 不会返回 ae.getKeyCode() 将是相同的 65。希望你明白这一点。欢迎询问更多。

【讨论】:

【参考方案6】:

您不应将 KeyListener 用于此类交互。而是使用键绑定,您可以在 Java Tutorial 中阅读。然后您可以使用InputEvent 掩码来表示何时按下各种修饰键。例如:

// Component that you want listening to your key
JComponent component = ...;
component.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
                            java.awt.event.InputEvent.CTRL_DOWN_MASK),
                    "actionMapKey");
component.getActionMap().put("actionMapKey",
                     someAction);

请参阅KeyStroke 的 javadoc,了解您在获取 KeyStroke 时可以使用的不同代码。这些修饰符可以通过或运算来表示各种键组合。比如

KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
                       java.awt.event.InputEvent.CTRL_DOWN_MASK
                       | java.awt.event.InputEvent.SHIFT_DOWN_MASK)

表示按下Ctrl + Shift 键的时间。

编辑:正如已经指出的那样,这并不能回答您的问题,而应该被视为一些好的建议。

【讨论】:

我 100% 同意您推荐的按键绑定,并因此对您的答案投了赞成票,但这个答案并没有解决他的主要问题:捕获 alt + 两个不同的按键组合。跨度> 你是完全正确的。我没有正确阅读问题。 感谢@Jonathan Spooner 无论如何推荐键绑定。这很有意义,特别是因为它解决了很多人通常使用KeyListeners 时遇到的焦点问题。 第二。每天的键绑定+1,也许我想念那里JComponent.WHEN_IN_FOCUSED_WINDOW “正如已经指出的那样,这并不能回答你的问题,而应该被视为一些好的建议。” 见Is “Don't do it” a valid answer? 摘要:哎呀,是的!

以上是关于KeyListener 如何检测组合键(例如,ALT + 1 + 1)的主要内容,如果未能解决你的问题,请参考以下文章

Swing的KeyListener和多个键同时按下

如何为 JavaFX 编写 KeyListener

单击按钮后keylistener不起作用

如何检测 C++ 中的组合键输入?

如何使 KeyListener 起作用?

如何检测单个控制键盘事件而不是键组合?