Well, it won't wait but you can keep track of it for yourself with something like this
// class level
long lastKeyPress = System.currentTimeMillis();
int lastKey=0;
// whichever keys you need
final static int KEY_1 = KeyEvent.VK_A;
final static int KEY_2 = KeyEvent.VK_B;
// whatever interval you need for "at the same time"
// 50ms seems to work ok
final static int TIME_LIMIT = 50;
// wherever you set up the KeyListener
component.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e){
if (System.currentTimeMillis() - lastKeyPress < TIME_LIMIT && ((lastKey|e.getKeyCode())==(KEY_2|KEY_1)) ){
// within time limit
doSpecial();
}
lastKeyPress = System.currentTimeMillis();
lastKey = e.getKeyCode();
}
});
Ezzaral
null
16,126 posts since May 2007
Reputation Points: 3,294
Solved Threads: 875
Skill Endorsements: 28
I'd say yes, you're probably going to have to deal with threads for that. It sounds like you have a decent handle on how to proceed with it via the KeyInterpreter. If you queue the received keys and process them in a timer event you can dispatch to the appropriate actions. Of course, tuning that dispatch to prevent lagging of the individual A and B actions or allowing the transitions such as A to AB or B to AB may be the tricky part.
It sounds like the transition states are what you are wanting to avoid, so I would think if you keep the timer event short enough you can dispatch to the appropriate method based on the queued keys.
Ezzaral
null
16,126 posts since May 2007
Reputation Points: 3,294
Solved Threads: 875
Skill Endorsements: 28
Well acctualy I'm clueless with threads, I just happen to be using one off a tutorial for my animation. I guess at this point I just have to do some research on threads. By the way do you think 50 is faster than humanly possible to double tap a key?
Not sure, System.out.println(System.currentTimeMillis() - lastTime) is a decent way to find out though.
If you have the time, mind answering this question...
I was following this example: ( http://www.javaworld.com/jw-03-1996/animation/Example1Applet.html ) and what confuses me is the start function. Being that the new thread is "this" and in the start function, start is called in the new thread; how's that not a looping effect?
Yes,I can see where it would be a bit confusing in that both threads and applets have start() methods. In the applet start() method, they are creating a new Thread with the constructor Thread(Runnable target) . Because they have defined the applet to implement the Runnable interface and provided a run() method in the class, they can pass the class object "this" to the Thread constructor. They then start that thread running with the animator.start() call. The fact that it was done in the applet start() method does make it a bit awkward to read if you aren't used to threads.
Ezzaral
null
16,126 posts since May 2007
Reputation Points: 3,294
Solved Threads: 875
Skill Endorsements: 28
I was playing around with a timer-based key processor and I think you are going to have issues with key listener. Here is the processor I wrote
class KeyProcessor extends javax.swing.Timer {
List keyQueue = new ArrayList();
final static int KEY_1 = KeyEvent.VK_A;
final static int KEY_2 = KeyEvent.VK_B;
public KeyProcessor(int delay, ActionListener listener) {
super(delay, null);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (keyQueue.contains(KEY_1) && keyQueue.contains(KEY_2))
lblState.setText("State A+B");
else if (keyQueue.contains(KEY_1))
lblState.setText("State A");
else if (keyQueue.contains(KEY_2))
lblState.setText("State B");
keyQueue.clear();
}
});
}
I then started that up and attached a KeyListener to feed the key queue
keyProcessor = new KeyProcessor(200,null);
txtInput.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e){
keyProcessor.queueKey(e.getKeyCode());
}
});
keyProcessor.start();
It will process the A+B state fine just once if the key combo comes in within the time slice, but if the keys are held down then only the last key pressed gets repeated, so the state will change either A or B. Now, I am running this on a Windows XP machine so maybe it's a system specific thing with how repeated keypresses are handled, but it is obviously an issue on Windows.
I haven't had to do anything like this with KeyListeners before, so maybe there is some other technique to listen for both of those keys, but keyPressed() isn't receiving both key code.
Ezzaral
null
16,126 posts since May 2007
Reputation Points: 3,294
Solved Threads: 875
Skill Endorsements: 28
You will want to call the start() method to begin thread execution instead of calling run() directly. Start() sets up other necessary things and then calls run(), which is why the Runnable interface requires you to override run() to provide the actual "what am I supposed to do" part of the thread.
Ezzaral
null
16,126 posts since May 2007
Reputation Points: 3,294
Solved Threads: 875
Skill Endorsements: 28
I did some more playing around with it this morning and this seems to work
class KeyProcessor extends javax.swing.Timer {
final static int KEY_1 = KeyEvent.VK_A;
final static int KEY_2 = KeyEvent.VK_B;
Map<Integer,Boolean> keystate = new Hashtable<Integer,Boolean>();
public KeyProcessor(int delay, ActionListener listener) {
super(delay, null);
keystate.put (KEY_1,false);
keystate.put(KEY_2,false);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (keystate.get(KEY_1)&&keystate.get(KEY_2))
lblState.setText("State A+B");
else if (keystate.get(KEY_1))
lblState.setText("State A");
else if (keystate.get(KEY_2))
lblState.setText("State B");
else
lblState.setText("none");
}
});
}
public void setKeystate(int keycode, boolean pressed){
keystate.put(keycode, pressed);
}
}
// This part wherever you are setting up your key listener.
// 200ms seemed to work fine as a time interval
// but tune as you like
keyProcessor = new KeyProcessor(200,null);
txtInput.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e){
keyProcessor.setKeystate(e.getKeyCode(),true);
}
public void keyReleased(KeyEvent e){
keyProcessor.setKeystate(e.getKeyCode(),false);
}
});
keyProcessor.start();
Ezzaral
null
16,126 posts since May 2007
Reputation Points: 3,294
Solved Threads: 875
Skill Endorsements: 28
Ezzaral
null
16,126 posts since May 2007
Reputation Points: 3,294
Solved Threads: 875
Skill Endorsements: 28