Swing's KeyListener and multiple keys pressed at the same time
开发者_如何学编程is there any conventional way in swing of tracking down the events, when two keyboard keys are pressed at the same time? I have a couple of ideas e.g. remembering the key and event generation time so that we could in a consecutive event handler invocation check the time difference between these two events and decide, whether it's a two-button event or not. But it looks like a kludge.
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 */ }
}
The KeyListener interface allows detecting key pressing and releasing separately. Therefore, you can maintain a set of "active keys", i.e. keys which have been pressed but not released yet.
If after 7 years I tried to do this (just to see if it is possible), someone else might as well...
The code below controls the movement with 8 axis direction, explanation in the comments. But basically, the KeyListener
just define where it is possible to move, then a Thread
will combine the possible destinations and move the JLabel
.
package tests;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Move8Axis extends JFrame {
private static final long serialVersionUID = 7722803326073073681L;
private boolean left = false;
private boolean up = false;
private boolean down = false;
private boolean right = false;
private JLabel lbl = new JLabel("#");
public Move8Axis() {
// Just setting up the window and objects
setSize(400, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
lbl.setBounds(100, 100, 20, 20);
add(lbl);
setLocationRelativeTo(null);
// Key listener, will not move the JLabel, just set where to
addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) left = false;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) right = false;
if (e.getKeyCode() == KeyEvent.VK_UP) up = false;
if (e.getKeyCode() == KeyEvent.VK_DOWN) down = false;
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) left = true;
if (e.getKeyCode() == KeyEvent.VK_RIGHT) right = true;
if (e.getKeyCode() == KeyEvent.VK_UP) up = true;
if (e.getKeyCode() == KeyEvent.VK_DOWN) down = true;
}
});
// This thread will read the 4 variables left/right/up/down at every 30 milliseconds
// It will check the combination of keys (left and up, right and down, just left, just up...)
// And move the label 3 pixels
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
if (left && up) {
lbl.setBounds(lbl.getX() - 3, lbl.getY() - 3, 20, 20);
} else if (left && down) {
lbl.setBounds(lbl.getX() - 3, lbl.getY() + 3, 20, 20);
} else if (right && up) {
lbl.setBounds(lbl.getX() + 3, lbl.getY() - 3, 20, 20);
} else if (right && down) {
lbl.setBounds(lbl.getX() + 3, lbl.getY() + 3, 20, 20);
} else if (left) {
lbl.setBounds(lbl.getX() - 3, lbl.getY(), 20, 20);
} else if (up) {
lbl.setBounds(lbl.getX(), lbl.getY() - 3, 20, 20);
} else if (right) {
lbl.setBounds(lbl.getX() + 3, lbl.getY(), 20, 20);
} else if (down) {
lbl.setBounds(lbl.getX(), lbl.getY() + 3, 20, 20);
}
Thread.sleep(30);
}
} catch (Exception ex) {
ex.printStackTrace();
System.exit(0);
}
}
}).start();
}
public static void main(String[] args) {
new Move8Axis();
}
}
精彩评论