Java KeyBindings Combination does not work

旧街凉风 提交于 2019-12-10 11:36:18

问题


I'm struggling with creating a way to identify key combinations. Before I can even set any booleans, I noticed that certain key combinations lead to ignoring other keys.

package question;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class Example extends JPanel {

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

public Example() {

    setBackground(Color.DARK_GRAY);
    setPreferredSize(new Dimension(500,500));
    setFocusable(true);
    requestFocusInWindow();

    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "action_a");
    getActionMap().put("action_a", new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("A has been pressed!");
        }
    });
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "action_s");
    getActionMap().put("action_s", new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("S has been pressed!");
        }
    });
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "action_d");
    getActionMap().put("action_d", new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("D has been pressed!"); // This code is reached, even when you are holding down the A key and S key 
        }
    });getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_J, 0), "action_j");
    getActionMap().put("action_j", new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("J has been pressed!");
        }
    });
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_K, 0), "action_k");
    getActionMap().put("action_k", new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("K has been pressed!");
        }
    });
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_L, 0), "action_l");
    getActionMap().put("action_l", new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("L has been pressed!"); // This code is never reached when you hold down the J key and K key
        }
    });

    JFrame frame;       
    frame = new JFrame("KeyBinding problem");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(this, BorderLayout.CENTER);
    frame.pack();       
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

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

I have now used KeyBindings as recommended in order to enable key combinations. But, the problem I'm facing is that not all keys are registered when certain keys are pressed at once. With my example, try the following scenario:

Start the example and hold down the A key. The console will continously print out "A has been pressed!". Now, while still holding down the A key, add the S key in addition and hold it down, aswell. The console will now stop printing out "A has been pressed!" and print out "S has been pressed!" continously, instead. Now hold down the A key and the S key and the D key. This will lead to the console continously printing out "D has been pressed!".

Now, restart everything, but instead of using the A, S and D key, use the J, K and L key. This will only be working with J and K and the L key will be ignored.

-> I'm using Windows 8.1 (64-Bit) by the way. With an Aspire E1-772G laptop.

Can someone please tell me why this is happening and how I can work around or even fix this problem? Thanks in advance!

cheers.

*edit I have added another example, which also shows the problem visually. It is not possible for me to get all labels to turn red at once. The combination of J+K+L seems problematic for me. This cannot be related to the amount of keys pressed at once , because it's working for 6 keys in my main program, aswell. It's just the combination of J+K, which seems to stop firing the KeyEvents for the L key. This also appears to happen with KeyListeners, as shown in the example below.

package question;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.BitSet;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Example extends JPanel implements KeyListener, Runnable {

/**
 * 
 */
private static final long serialVersionUID = 1L;
private BitSet bitSet;
private Thread thread;
private JLabel a_key, s_key, d_key, j_key, k_key, l_key;

public Example() {      
    setBackground(Color.DARK_GRAY);
    setPreferredSize(new Dimension(700,300));
    addKeyListener(this);
    setFocusable(true);
    requestFocusInWindow();

    bitSet = new BitSet(256);
    thread = new Thread(this);

    a_key = new JLabel("A");
    a_key.setBackground(Color.YELLOW);
    a_key.setPreferredSize(new Dimension(50,50));
    a_key.setOpaque(true);

    s_key = new JLabel("S");
    s_key.setBackground(Color.YELLOW);
    s_key.setPreferredSize(new Dimension(50,50));
    s_key.setOpaque(true);

    d_key = new JLabel("D");
    d_key.setBackground(Color.YELLOW);
    d_key.setPreferredSize(new Dimension(50,50));
    d_key.setOpaque(true);

    j_key = new JLabel("J");
    j_key.setBackground(Color.YELLOW);
    j_key.setPreferredSize(new Dimension(50,50));
    j_key.setOpaque(true);

    k_key = new JLabel("K");
    k_key.setBackground(Color.YELLOW);
    k_key.setPreferredSize(new Dimension(50,50));
    k_key.setOpaque(true);

    l_key   = new JLabel("L");
    l_key.setBackground(Color.YELLOW);
    l_key.setPreferredSize(new Dimension(50,50));
    l_key.setOpaque(true);

    add(a_key);
    add(s_key);
    add(d_key);
    add(j_key);
    add(k_key);
    add(l_key);

    JFrame frame;       
    frame = new JFrame("Key Event problem");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(this, BorderLayout.CENTER);
    frame.pack();       
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

    thread.start();
}

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

@Override
public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();
    if(bitSet.get(keyCode) == false) {
        bitSet.set(keyCode);
    }       
}

@Override
public void keyReleased(KeyEvent e) {
    int keyCode = e.getKeyCode();
    bitSet.clear(keyCode);
}

@Override
public void keyTyped(KeyEvent e) {

}

private boolean isKeyPressed(int keyCode) {
    return bitSet.get(keyCode);
}

@Override
public void run() {
    while(true) {
        if(isKeyPressed(KeyEvent.VK_A)) {
            a_key.setBackground(Color.red);
        }
        else {
            if(a_key.getBackground() == Color.red) {
                a_key.setBackground(Color.yellow);
            }               
        }
        if(isKeyPressed(KeyEvent.VK_S)) {
            s_key.setBackground(Color.red);
        }
        else {
            if(s_key.getBackground() == Color.red) {
                s_key.setBackground(Color.yellow);
            }               
        }
        if(isKeyPressed(KeyEvent.VK_D)) {
            d_key.setBackground(Color.red);
        }
        else {
            if(d_key.getBackground() == Color.red) {
                d_key.setBackground(Color.yellow);
            }               
        }
        if(isKeyPressed(KeyEvent.VK_J)) {
            j_key.setBackground(Color.red);
        }
        else {
            if(j_key.getBackground() == Color.red) {
                j_key.setBackground(Color.yellow);
            }               
        }
        if(isKeyPressed(KeyEvent.VK_K)) {
            k_key.setBackground(Color.red);
        }
        else {
            if(k_key.getBackground() == Color.red) {
                k_key.setBackground(Color.yellow);
            }               
        }
        if(isKeyPressed(KeyEvent.VK_L)) {
            l_key.setBackground(Color.red);
        }
        else {
            if(l_key.getBackground() == Color.red) {
                l_key.setBackground(Color.yellow);
            }               
        }
    }
}
}

回答1:


Possibly this has something to do with key rollover: https://en.wikipedia.org/wiki/Rollover_(key) Some keyboards give special connections to the WASD keys as they are used frequently in gaming.



来源:https://stackoverflow.com/questions/28389177/java-keybindings-combination-does-not-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!