KeyEvent keyPressed组合键被阻止 [英] KeyEvent keyPressed key combination is blocked

查看:129
本文介绍了KeyEvent keyPressed组合键被阻止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为以下问题苦苦挣扎了好几个小时,找不到解决方案.我目前正在开发音乐/节奏游戏,在该游戏中,用户必须在正确的时间按下某些键才能得分.

I've been struggling with the following problem for quite some hours now and can't find the solution. I'm currently working on a music/rhythm game, in which the user has to press certain keys at the right time to score points.

现在,由于它应该类似于弹钢琴,因此也必须要有组合键.游戏中目前有7个键(A,S,D,SPACE,J,K和L),除了K + L + ANY之外,它们的每种组合都可以正常工作.

Now, since it's supposed to be similar to playing piano, key combinations have to be possible, aswell. There are currently 7 keys in the game (A, S, D, SPACE, J, K and L) and every combination of these are working fine except for K + L + ANY.

起初,我认为可能无法一次按下两个以上的键,但是同时按下A,S,D,SPACE,J和K都没问题,但是当同时按下L时,它只是不响应(不触发KeyEvent).

At first, I thought that it might not be possible to press more than 2 keys at once, but A, S, D, SPACE, J and K at the same time are no problem, but when L is pressed aswell, it simply does not respond (no KeyEvent fired).

这似乎也是许多其他按键组合的问题.我只发现Y,X,D,T,Z,O和M(欧洲键盘)是可以同时按下的一种有效的7键组合.但是,这对于玩家来说并不是一个舒适的组合键.

This seems to be the problem with many other key combinations aswell. I've only found Y, X, D, T, Z, O and M (European keyboard) to be one working 7 key combination that can be pressed at once. This however is not a comfortable key combination for the player.

这是我代码中的相关部分:

Here is the relevant part from my code:

package question;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class Example extends Canvas implements KeyListener {

/**
 * 
 */
private static final long serialVersionUID = 1L;

public Example() {
    JFrame frame;       
    frame = new JFrame("KeyEvent problem");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(this, BorderLayout.CENTER);
    frame.pack();       
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    setFocusable(true);
    addKeyListener(this);
    requestFocusInWindow(); 
}

public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();
    if(keyCode == KeyEvent.VK_A) {
        //lines.get(0).setActive(true);
    }
    else if(keyCode == KeyEvent.VK_S) {
        //lines.get(1).setActive(true);
    }
    else if(keyCode == KeyEvent.VK_D) {
    //  lines.get(2).setActive(true);
    }
    else if(keyCode == KeyEvent.VK_SPACE) {
        //lines.get(3).setActive(true);
    }
    else if(keyCode == KeyEvent.VK_J) {
        //lines.get(4).setActive(true);
    }
    else if(keyCode == KeyEvent.VK_K) {
        //lines.get(5).setActive(true);
    }
    else if(keyCode == KeyEvent.VK_L) {
        //lines.get(6).setActive(true);
    }

    System.out.println("keycode: " + keyCode + " keyChar: " + e.getKeyChar());
}

public void keyReleased(KeyEvent e) {
    int keyCode = e.getKeyCode();
    if(keyCode == KeyEvent.VK_A) {
        //lines.get(0).setActive(false);
    }
    else if(keyCode == KeyEvent.VK_S) {
        //lines.get(1).setActive(false);
    }
    else if(keyCode == KeyEvent.VK_D) {
        //lines.get(2).setActive(false);
    }
    else if(keyCode == KeyEvent.VK_SPACE) {
        //lines.get(3).setActive(false);
    }
    else if(keyCode == KeyEvent.VK_J) {
        //lines.get(4).setActive(false);
    }
    else if(keyCode == KeyEvent.VK_K) {
        //lines.get(5).setActive(false);
    }
    else if(keyCode == KeyEvent.VK_L) {
        //lines.get(6).setActive(false);
    }       
}

public void keyTyped(KeyEvent arg0) {}

public static void main(String[] args) {
    Example example = new Example();
}

}

lines.get(index).setActive(boolean b)只是为游戏中按键的某些图形表示设置标志.但是,当您按下按钮时,您也可以在控制台中看到它.它们的keyCode和KeyChar都是垃圾邮件,当按住每个键时,这可以正常工作,并且最近按下的键在控制台中表示.但是,这不适用于J + K + L.

Where lines.get(index).setActive(boolean b) just sets a flag for some graphical representation of the keys in-game. But, you can also see this in the console when pressing the buttons. They keyCode and KeyChar is spammed, when holding down each key, this works fine and the most recently pressed key is represented in the console. This does not work with J + K + L, though.

在按住A,然后按A + S,然后按A + S + D时,此示例的控制台将显示的内容:

键码:65键字符:a

键码:65键字符:a

键码:65键字符:a

密钥码:83 keyChar:s

密钥码:83 keyChar:s

密钥码:83 keyChar:s

键码:68键字符:d

键码:68键字符:d

键码:68键字符:d

What the console of this example will show when pressing and holding A then A+S and then A+S+D:

keycode: 65 keyChar: a

keycode: 65 keyChar: a

keycode: 65 keyChar: a

keycode: 83 keyChar: s

keycode: 83 keyChar: s

keycode: 83 keyChar: s

keycode: 68 keyChar: d

keycode: 68 keyChar: d

keycode: 68 keyChar: d

J然后J + K然后J + K + L会导致以下情况:

键码:74键字符:j

键码:74键字符:j

键码:74键字符:j

关键码:75 keyChar:k

关键码:75 keyChar:k

关键码:75 keyChar:k

(即使按了它,L也丢失了)

Whereas J then J+K then J+K+L leads to the following:

keycode: 74 keyChar: j

keycode: 74 keyChar: j

keycode: 74 keyChar: j

keycode: 75 keyChar: k

keycode: 75 keyChar: k

keycode: 75 keyChar: k

(L is missing, eventhough it is pressed)

我是否有可能以某种方式更改此设置?为什么会这样呢?我希望不必使用KeyBindings,因为我现在不使用JComponent,而是使用Canvas.

Is there any chance I can change this somehow? Why is this happening? I'm hoping not to have to use KeyBindings, because I'm not working with a JComponent, but Canvas at the moment.

欢呼.

推荐答案

这似乎是操作系统和/或键盘硬件的限制,这是我使用的测试代码,只能按六个键一次,无论组合如何.在Windows 7和MacOS X Yosemite上都经过测试

This seems to be a limitation with the OS and/or keyboard hardware, this is the test code I used with which I was only able to get six keys pressed at a time, regardless of the combinations. Tested on both Windows 7 and MacOS X Yosemite

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Map<String, Boolean> mapKeys;

        public TestPane() {
            mapKeys = new HashMap<>();
            mapKeys.put("A", false);
            mapKeys.put("S", false);
            mapKeys.put("D", false);
            mapKeys.put(" ", false);
            mapKeys.put("J", false);
            mapKeys.put("K", false);
            mapKeys.put("L", false);

            bindKey(KeyEvent.VK_A, "A");
            bindKey(KeyEvent.VK_S, "S");
            bindKey(KeyEvent.VK_D, "D");
            bindKey(KeyEvent.VK_SPACE, " ");
            bindKey(KeyEvent.VK_J, "J");
            bindKey(KeyEvent.VK_K, "K");
            bindKey(KeyEvent.VK_L, "L");
        }

        protected void bindKey(int keyCode, String name) {

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(keyCode, 0, false), "pressed." + name);
            im.put(KeyStroke.getKeyStroke(keyCode, 0, true), "released." + name);

            am.put("pressed." + name, new KeyAction(name, true));
            am.put("released." + name, new KeyAction(name, false));

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            FontMetrics fm = g2d.getFontMetrics();
            int charWidth = fm.charWidth('M') + 2;
            int charHeight = fm.getHeight();
            int x = (getWidth() - ((charWidth + 2) * mapKeys.size())) / 2;
            int y = (getHeight() - charHeight) / 2;
            for (String name : mapKeys.keySet()) {
                boolean state = mapKeys.get(name);
                int xPos = x + ((charWidth - fm.stringWidth(name))) / 2;
                Rectangle bounds = new Rectangle(x, y, charWidth, charHeight);
                if (state) {
                    g2d.setColor(Color.RED);
                    g2d.fill(bounds);
                }
                g2d.setColor(Color.BLACK);
                g2d.draw(bounds);
                g2d.drawString(name, xPos, y + fm.getAscent());
                x += charWidth + 2;
            }
            g2d.dispose();
        }

        public class KeyAction extends AbstractAction {

            private String name;
            private boolean state;

            public KeyAction(String name, boolean state) {
                this.name = name;
                this.state = state;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                mapKeys.put(name, state);
                repaint();
            }

        }

    }

}

这篇关于KeyEvent keyPressed组合键被阻止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆