Swing's Keylistener and Multiple Keys Pressed at the Same Time

Swing's KeyListener and multiple keys pressed at the same time

Use a collection to remember which keys are currently pressed and check to see if more than one key is pressed every time a key is pressed.

class MultiKeyPressListener implements KeyListener {
// Set of currently pressed keys
private final Set<Integer> pressedKeys = new HashSet<>();

@Override
public synchronized void keyPressed(KeyEvent e) {
pressedKeys.add(e.getKeyCode());
Point offset = new Point();
if (!pressedKeys.isEmpty()) {
for (Iterator<Integer> it = pressedKeys.iterator(); it.hasNext();) {
switch (it.next()) {
case KeyEvent.VK_W:
case KeyEvent.VK_UP:
offset.y = -1;
break;
case KeyEvent.VK_A:
case KeyEvent.VK_LEFT:
offset.x = -1;
break;
case KeyEvent.VK_S:
case KeyEvent.VK_DOWN:
offset.y = 1;
break;
case KeyEvent.VK_D:
case KeyEvent.VK_RIGHT:
offset.x = 1;
break;
}
}
}
System.out.println(offset); // Do something with the offset.
}

@Override
public synchronized void keyReleased(KeyEvent e) {
pressedKeys.remove(e.getKeyCode());
}

@Override
public void keyTyped(KeyEvent e) { /* Event not used */ }
}

Java - KeyListener Multiple Keys

A lot of people have that problem. It is called Keyboard Ghosting and means that some combinations simply don't work on cheap keyboards. Thats why high class gaming keyboards exists. So nothing wrong with your code. No optimization possible. You need to use key combination that work.
To proof my answer here are some links for you.

  • http://board.flashkit.com/board/showthread.php?789015-wont-respond-to-keyboard-up-left-and-space-at-the-same-time

  • http://forums.steampowered.com/forums/showthread.php?t=1928521

  • http://www.tomshardware.co.uk/answers/id-2159074/alt-space-bar-work-holding-left-arrow.html

  • https://unix.stackexchange.com/questions/268850/leftupspace-keys-not-working-on-thinkpad-x201

Two Keys pressed at the same time in java

    private final Set<Character> Keyspressed = new HashSet<Character>(); 

public void keyPressed(KeyEvent e){
pressed.add(e.getKeyChar());
if (Keyspressed.size() > 1) {
//size is greator than one which means you
//have pressed more than one key.
//now your set contains all pressed keys. iterate it and fine out which was pressed.
foo(Keyspressed);
}
}
public void foo(Set<Character> Keyspressed){
boolean Apressed = false;
boolean Wpressed = false;
boolean Spressed = false;
boolean Dpressed = false;

for(Character e : Keyspressed){
if(e==KeyEvent.VK_A){
Apressed = true;
}else if(e==KeyEvent.VK_S){
Spressed = true;
}else if(e==KeyEvent.VK_D){
Dpressed = true;
}else if(e==KeyEvent.VK_W){
Wpressed = true;
}
}
if(Apressed && Spressed){
//your logic
}

}

you can add all the pressed keys into a set<Character> and implement a function to iterate over the pressed Keys.

Multiple Keys in KeyEvent Listener

To be honest, KeyListener has many limitations and is cumbersome to use (IMHO), instead, I would simply take advantage of the key bindings API, which generally provides you with a greater deal of flexibility and potentional for resuse.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class KeyListenerTest {

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

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

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

public class TestPane extends JPanel {

private JLabel lbl;
private boolean fullScreen = false;

public TestPane() {
lbl = new JLabel("Normal");
setLayout(new GridBagLayout());
add(lbl);

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

im.put(KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK), "FullScreen");
am.put("FullScreen", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (fullScreen) {
lbl.setText("Normal");
} else {
lbl.setText("Full Screen");
}
fullScreen = !fullScreen;
}
});

}

}

}

And just so you don't think I'm completely bias, here's an example using KeyListener...

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class KeyListenerTest {

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

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

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

public class TestPane extends JPanel {

private JLabel lbl;
private boolean fullScreen = false;

public TestPane() {
lbl = new JLabel("Normal");
setLayout(new GridBagLayout());
add(lbl);

setFocusable(true);
addMouseListener(new MouseAdapter() {

@Override
public void mouseClicked(MouseEvent e) {
requestFocusInWindow();
}

});

addKeyListener(new KeyAdapter() {

@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_F && e.isControlDown()) {
if (fullScreen) {
lbl.setText("Normal");
} else {
lbl.setText("Full Screen");
}
fullScreen = !fullScreen;
}
}

});
}
}
}

Java swing - Processing simultaneous key presses with key bindings

I personally would use the KeyListener interface to keep track of what the user has typed and then just register within a List the keys that have been pressed (without releasing) and then collect them once any key has been released.

Make sure though to add to the list only the keys that are not present yet because the keyPressed event is fired multiple times while the user is holding down a key.

I've also created a little sample to give you the idea.

public class MyClass extends JFrame implements KeyListener {

private JTextArea textArea;
private List<Character> listKeys;

public MyClass() {
setTitle("test");

listKeys = new ArrayList<>();
textArea = new JTextArea();
textArea.addKeyListener(this);

setLayout(new BorderLayout());
add(textArea, BorderLayout.CENTER);

setLocation(50, 50);
setSize(500, 500);
setVisible(true);
}

@Override
public void keyTyped(KeyEvent e) {
}

@Override
public void keyPressed(KeyEvent e) {
if (!listKeys.contains(e.getKeyChar())) {
listKeys.add(e.getKeyChar());
}
}

@Override
public void keyReleased(KeyEvent e) {
if (listKeys.isEmpty()) {
return;
}

if (listKeys.size() > 1) {
System.out.print("The key combination ");
} else {
System.out.print("The key ");
}
for (Character c : listKeys) {
System.out.print(c + " ");
}
System.out.println("has been entered");
listKeys.clear();
}

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

Scala/Swing - Responding to multiple key events that are happening at the same time

Make a buffer that holds all the keys that are pressed

var pressedKeys = Buffer[Key.Value]()

When key is pressed add the key to the buffer and check if the buffer contains some wanted key values

 reactions += {
case KeyPressed(_, key, _, _) =>
pressedKeys += key
if(pressedKeys contains Key.Space){ //Do if Space
label.text = "Space is down"
if(pressedKeys contains Key.Up) //Do if Space and Up
label.text = "Space and Up are down"
}else if(pressedKeys contains Key.Up)//Do if Up
label.text = "Up is down"

Clear the buffer when button released

            case KeyReleased(_, key, _, _) =>
pressedKeys = Buffer[Key.Value]()
/* I tried only to remove the last key with
* pressedKeys -= key, but ended up working
*badly, because in many occasions the program
*did not remove the key*/


Related Topics



Leave a reply



Submit