|
Comments
|
Submitted On 03-OCT-2004
gdeg
A workaround for this X11/Unix problem is described here:
http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/x11/SDL_x11events.c?rev=1.15
/* Check to see if this is a repeated key.
(idea shamelessly lifted from GII -- thanks guys! :)
*/
static int X11_KeyRepeat(Display *display, XEvent *event)
{
XEvent peekevent;
int repeated;
repeated = 0;
if ( XPending(display) ) {
XPeekEvent(display, &peekevent);
if ( (peekevent.type == KeyPress) &&
(peekevent.xkey.keycode == event->xkey.keycode) &&
((peekevent.xkey.time-event->xkey.time) < 2) ) {
repeated = 1;
XNextEvent(display, &peekevent);
}
}
return(repeated);
}
I tried doing the same from within Java, using EventQueue.peekEvent(), and IIRC it worked correctly for about 10 seconds after the program started - then the queue was empty when i checked.
Java on Windows and Mac don't generate these bogus events, and provides the information needed to distinguish between keys pressed, keys repeated and keys released. The Unix way is simply broken here, and nobody will want Java to be broken the same way.
Submitted On 25-MAY-2007
Ekipur
The program xev on my Linux system revealed an interesting detail: The difference in time between a KeyRelease and a succeeding KeyPress is zero, while the difference between a KeyPress and a KeyRelease is even greater than zero; so to detect a real, final KeyRelease, you have to wait only one millisecond when a KeyRelease event occures. If then after this millisecond there is no KeyPress event we've got that final key release.
Based on this knowledge i implemented the
following class:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.Timer;
public class TimedKeyListener
implements KeyListener, ActionListener {
private final Timer timer;
private boolean released = false;
private KeyEvent releaseEvent;
public TimedKeyListener() {
/* Just a millisecond is necessary
* to detect a final key release.
*/
timer = new Timer(1, this);
}
public void keyPressed(KeyEvent e) {
released = false;
/* This key pressed event indicates
* that the recent key release event
* was no real, final key release,
* so we have to stop the timer.
*/
timer.stop();
}
public void keyReleased(KeyEvent e) {
if (!released) {
/* Store the current key release
* event, as it is sent finally
* by our timer.
*/
releaseEvent = e;
timer.restart();
}
}
public void keyTyped(KeyEvent e) {
}
public void actionPerformed(ActionEvent e) {
/* When the timer sends its action event
* we know that no key press event has
* followed the last key release event,
* so we resend the recently stored
* key release event; but now we set
* released to true to indicate that
* we've got the final key release.
*/
released = true;
timer.stop();
keyReleased(releaseEvent);
}
/**
* Do we have a real final key release?
* @return True, if the KeyEvent obtained
* via keyReleased() is a real final key
* release.
*/
protected boolean getReleased() {
return released;
}
}
Now you can use TimedKeyListener as shown in the following code snippet:
public class TimedKeyListenerDemo extends JFrame {
public TimedKeyListenerDemo() {
// some code...
TimedKeyListener kl = new TimedKeyListener() {
public void keyPressed(KeyEvent evt) {
// Must be called prior to any other action!
super.keyPressed(evt);
System.out.println(".");
}
public void keyReleased(KeyEvent evt) {
// Must be called prior to any other action!
super.keyReleased(evt);
// Do we have a real final key release?
if (getReleased()) {
// Yes, indeed :)
System.out.println("#");
}
}
};
JButton button = new JButton("Press any key");
button.addKeyListener(kl);
// some code...
}
}
Submitted On 25-JUN-2007
Ekipur
For a final version of TimedKeyListener.java, please take a look at the http://www.arco.in-berlin.de/keyevent.html
Submitted On 13-JUN-2008
oakidoaki
Quote: "most people will want Java applications
to act the same as other applications on their system"
I don't agree with this. If Java is based on platform independence, there should be only one "Java-Way" of doing it. As it is now, I have to check for the operating system inside my Java code to know what kind of behaviour to expect from my key events!
Submitted On 16-SEP-2008
grigor.iliev
Currently I'm implementing a virtual MIDI keyboard and I faced this bug. I find it very annoying and I'm amazed how 10 years are not enough for fixing it. I thought that the prime objective of java is write once, run everywhere.
If you really need backwards compatibility for a bug, at least provide some method like isAutoRepeat() to KeyEvent class.
Submitted On 23-APR-2009
vickirk
Maybe oracle will change the emphasis of which bugs to fix based on target platform independence so this bug can get raised in priority? This was raised almost 11 years ago.
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|