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

21

如何让我的自定义监听(或)+多个其他键的组合?

假设我有11个不同的操作,我希望根据按下的键的组合执行这些操作。显然, - 都没有任何问题,但对于(或类似“ALT + 10”的描述),我在网上(或自己的思考中)找不到好的解决方案。 我并不确定这个计时器解决方案是唯一可行的方法。

非常感谢提前的任何建议!

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


ALT10实际上是第11个操作... 我通常也会试图避免需要两只手按下的东西(因为1和0通常位于键盘的两端)- 尝试使用不同/额外的修改键代替。此外,如果您尝试添加另一个热键,则不能使用ALT11... - Clockwork-Muse
@X-Zero:抱歉,你是对的,这将是第11个操作 :). 我为什么要这样做是因为这些操作将在表格中具有int标题的列上调用。例如,如果用户想要更改第11列(称为“10”)中的数据,则会按下ALT + 1 + [同时释放ALT1] 0。我可以想象使用另一个键,如Shift或类似键,而不是使用ALT键。 - s.d
1
你最好分配一个快捷键,以呼出列选择对话框,用户可以在其中输入列索引或名称(名称比仅索引更好)。这样实现起来应该会容易得多,也更加方便用户。此外,你怎么能确定用户想要更改第11列而不是在第1列中放置数字1呢?还有,不要显示以0开头的列号,因为那只会让不习惯基于0的数组的人感到困惑。 - Clockwork-Muse
为了展示用户可能期望的发布或多步快捷键的工作方式,可以看一下Eclipse如何嵌套对话框。具体来说,松开按键会弹出初始对话框,进一步按键会激活该对话框上的对象。您的用户可能会期望这种行为,而不是转向“十位数”快捷键方法(当您到达第100列时会发生什么?)。此外,即使您的快捷键非常有用,也要准备好用户从未找到或(潜在地拒绝)采用快捷键的情况。 - Clockwork-Muse
嗨 @X-Zero:该应用程序具有高度特定的用户群,他们习惯于使用数组(实际上他们知道自己正在处理数组),因此我认为以0开头的列号不是问题。我想要避免触发另一个弹出对话框的弹出对话框,并且由于速度很重要,用户应该能够键入ALT + 1 + 1(或者甚至是ALT + 1 + 1 + 1)然后弹出窗口出现以更新表格中的另一行中的数据。 ALT + X键组合保留用于在应用程序中“调用列”,因此我不需要担心“交叉使用”。 - s.d
@X-Zero 续:我会查看 Eclipse 嵌套对话框(我猜可以在源代码中找到它们,例如菜单?),感谢你的提示。如果实现这些热键比我想象中的更困难,我一定会“冒险”在其中增加一个按键来显示简单的列选择对话框。谢谢! - s.d
6个回答

31

在这种交互方式中,您不应该使用KeyListener。相反,您应该使用键绑定,您可以在Java教程中了解更多相关信息。然后,您可以使用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时可用的不同代码。这些修饰符可进行OR操作以表示各种键的组合,例如:

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

表示Ctrl + Shift键被按下的时刻。

编辑:正如已经指出的,这并不是回答您问题的方法,而应该只作为一些好的建议。


4
我完全同意你推荐使用按键绑定的建议,并因此点赞了你的回答,但是这个回答没有解决他的主要问题:捕捉同时按下alt和两个不同的按键的组合。 - Hovercraft Full Of Eels
你是完全正确的。我没有正确地阅读问题。 - Jonathan Spooner
感谢@Jonathan Spooner推荐按键绑定。这非常有意义,特别是因为它解决了很多人通常在使用KeyListener时遇到的焦点问题。 - s.d
每天第二个按键绑定+1,也许我错过了JComponent.WHEN_IN_FOCUSED_WINDOW - mKorbel
1
正如已经指出的那样,这并不能回答你的问题,而应该只被视为一些好建议。请参考“不做是一个有效的答案吗?” 总结:当然可以! - Andrew Thompson
显示剩余3条评论

21

您可以通过结合某些东西使用 KeyListener 来实现此目的。查看以下示例,应将其放置在重写的 keyPressed(KeyEvent e) 方法中。

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

当按下 Ctrl + a 时,字符串 Select All 将会显示。方法 e.isControlDown() 检查是否按下了 Ctrl 键。同样地,可以通过使用 e.isAltDown() 方法来检测 Alt 键组合。

这背后的逻辑是,e.getKeyChar() 返回按键的字符,e.getKeyCode() 返回其 ASCII 代码。当按下并保持 Ctrl 键时,e.getKeyChar() 不会返回 a,而 e.getKeyCode() 将是相同的 65。希望你明白这一点。如有更多问题,请随时询问。


2

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

似乎与您的一条评论冲突:

例如,如果用户想要更改第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
    }

0

我认为有一个更简单的方法,我正在使用。如果KeyEvent是ev,那么如果你调查一下:

(int)ev.getKeyChar()

你发现 ctrl-a 是 1,ctrl-b 是 2 等等。我想使用 ctrl-s 来保存。所以我只需使用:
(((int)ev.getKeyChar())==19)

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

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

不是。


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

0
我建议您考虑使用一些输入字段,而不是使用键组合,当窗口 isVisible() 并且被聚焦时。该字段可以隐藏,就像 Windows 的文件资源管理器中的隐藏文件名搜索(输入目录、输入文件名并将对应项聚焦),或者可见,就像在 Ubuntu 中一样。
键组合并不适用于包含除修饰符以外的多个键,尽管您可能能够实现这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接