|
|||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||
java.lang.Objectcom.brianziman.ui.UsefulKeyAdapter
public class UsefulKeyAdapter
This class wraps your KeyAdapter and suppresses spurious repeated events.
Written by Brian Ziman and available for download and comments at http://www.brianziman.com/r/post/stuff-200910092100.
When running in an X11 environment, it appears as though either Java or the windowing system stupidly generate lots of repeated key events when you hold a key down. As it is impractical to get users to reconfigure their systems, and Sun seems unable to fix this issue (having been reported nearly ten years ago). This adapter is an attempt to filter out the useless events.
Many people have whined about this, but few have fixed it. Some have tried, but their solutions are not as clean as my OCD nature requires. Here are some examples of what this is meant to handle:
The goal is to generate a KeyPressed event when a key is pressed, and to generate a KeyReleased event when a key is released. And ONLY when a key is pressed or released.
The class is tested with Java 1.6.0 on Ubuntu 8.10, but should theoretically work on any platform, even if that platform issues events properly anyway. That is, this SHOULD work in a cross platform manner. If it doesn't, please let me know and I may fix it.
You don't actually call any of the methods on this class, directly. When Java thinks it is receiving an event, it will call the methods in this class, which will, in turn, decide whether an event has actually occurred, and call YOUR methods when you probably intended them to be called.
Replace:
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) { ... }
public void keyReleased(KeyEvent e) { ... }
});
with
addKeyListener(new UsefulKeyAdapter(new KeyAdapter() {
public void keyPressed(KeyEvent e) { ... }
public void keyReleased(KeyEvent e) { ... }
}));
Don't use this for keyTyped() events. If you are interested in these sorts of events, the default behaviour is probably what you actually want.
See How to Write a Key Listener on Sun's web site for more details.
This algorithm queues up keyboard events as the system reports them, and then uses a separate thread to handle the desired events, and disregard the spurious events.
Testing has indicated that there is zero delay between the key released event and the subsequent key pressed event when that pair are generated spuriously, and that is the case in which they are ignored. The default tolerance is 10 ms, as it is possible that the system will not always generate spurious key events instantly, but that is still substantially faster than a physical keyboard is able to perform multiple physical actions.
This code uses an ArrayBlockingQueue so the thread will not spin while waiting for input. Most events are handled immediately, and no event will be delayed more than the specified maximum age (default 10 ms).
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
Copyright 2009-2010 Brian Ziman
Please contact me if you find flaws in this software, or have any other comments or suggestions.
| Constructor Summary | |
|---|---|
UsefulKeyAdapter(java.awt.event.KeyListener keyListener)
Creates a KeyListener implementation that delegates event handling to the specified KeyListener, after filtering out spurious key pressed and key released events. |
|
UsefulKeyAdapter(java.awt.event.KeyListener keyListener,
int maxAge)
Creates a KeyListener implementation that delegates event handling to the specified KeyListener, after filtering out spurious key pressed and key released events. |
|
| Method Summary | |
|---|---|
void |
finalize()
Disable the background thread when the adapter goes out of scope. |
void |
keyPressed(java.awt.event.KeyEvent e)
Delegates the key pressed event. |
void |
keyReleased(java.awt.event.KeyEvent e)
Delegates the key released event. |
void |
keyTyped(java.awt.event.KeyEvent e)
Don't use the UsefulKeyAdapter for keyTyped events. |
void |
run()
The run loop processes events as they are queued up. |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Constructor Detail |
|---|
public UsefulKeyAdapter(java.awt.event.KeyListener keyListener)
public UsefulKeyAdapter(java.awt.event.KeyListener keyListener,
int maxAge)
| Method Detail |
|---|
public void run()
The run loop processes events as they are queued up.
New algorithm:
All events get queued up in sequence.
A separate thread pulls events off in a tight loop.
If the head event is a key released event:
run in interface java.lang.Runnablepublic void keyPressed(java.awt.event.KeyEvent e)
keyPressed in interface java.awt.event.KeyListenerpublic void keyReleased(java.awt.event.KeyEvent e)
keyReleased in interface java.awt.event.KeyListenerpublic void keyTyped(java.awt.event.KeyEvent e)
keyTyped in interface java.awt.event.KeyListenerpublic void finalize()
finalize in class java.lang.Object
|
|||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||