This week's book giveaway is in the HTML/CSS/JavaScript forum.
We're giving away four copies of Practical SVG and have Chris Coyier on-line!
See this thread for details.
Win a copy of Practical SVG this week in the HTML/CSS/JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Dispatching keyPressed and keyReleased events in software.

 
Stevens Miller
Bartender
Posts: 1422
29
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would like to have a JButton receive a KEY_PRESSED event when another JButton receives a MOUSE_PRESSED event, and to have that first JButton receive a KEY_RELEASED event when the second JButton receives a MOUSE_RELEASED event. The idea is to have one button be a "puppet" that the other button controls as a kind of "puppeteer." To do this, I've added a MouseListener to the puppeteer, and a KeyListener to the puppet. I've also provided an ActionListener to the puppet. When the puppet JButton has the focus, a press on the actual physical space-bar sends a KeyEvent to the puppet, with the KEY_PRESSED parameter. Subsequently releasing the space-bar sends a KeyEvent to the puppet, with the KEY_RELEASED parameter. Subsequent to that, the puppet's ActionListener is called, as I would expect it to be.

However, when I click and hold down the mouse button on the puppeteer, the puppeteer receives a MouseEvent sent to its mousePressed MouseListener method which, in turn, creates a KeyEvent with the KEY_PRESSED parameter that is given to the top-most JFrame's dispatchEvent method. This results in the puppet JButton receiving a keyPressed event with the KEY_PRESSED parameter, just as when it received such an event pursuant to having the focus and my pressing the keyboard's space-bar. But, rather than waiting for a KeyEvent with the KEY_RELEASED parameter, the puppet's ActionListener is called immediately. When I release the mouse button, the puppeteer receives a mouseReleased event, and its MouseListener sends a KeyEvent to the puppet, with the KEY_RELEASED parameter. But the puppet, already having called its ActionListener, doesn't call it again. I would have expected the puppet not to call its ActionListener until after the puppeteer had sent it a keyReleased event.

Even more confusing, the puppet alternates between waiting for the puppeteer to send it a keyReleased event before calling its ActionListener, and not waiting for that keyReleased event, on every other press of the mouse button on the puppeteer. Here is my output when I run the program, the puppet has the focus, and I simply press and release the space-bar:

Puppet key pressed:
ID=401
KeyCode=32
ParamString='KEY_PRESSED,keyCode=32,keyText=Space,keyChar=' ',keyLocation=KEY_LOCATION_STANDARD,rawCode=32,primaryLevelUnicode=32,scancode=57,extendedKeyCode=0x20'

Puppet key released:
ID=402
KeyCode=32
ParamString='KEY_RELEASED,keyCode=32,keyText=Space,keyChar=' ',keyLocation=KEY_LOCATION_STANDARD,rawCode=32,primaryLevelUnicode=32,scancode=57,extendedKeyCode=0x20'

Puppet action performed.


That's what I expected. The puppet's KeyListener receives the keyPressed event, then receives the keyReleased event, then calls its ActionListener. Here's what I get when I run the program and click once with the mouse on the puppeteer:

Puppeteer Mouse Pressed

Puppet key pressed:
ID=401
KeyCode=32
ParamString='KEY_PRESSED,keyCode=32,keyText=Space,keyChar=' ',keyLocation=KEY_LOCATION_STANDARD,rawCode=0,primaryLevelUnicode=0,scancode=0,extendedKeyCode=0x0'

Puppet action performed.

Puppeteer Mouse Released

Puppet key released:
ID=402
KeyCode=32
ParamString='KEY_RELEASED,keyCode=32,keyText=Space,keyChar=' ',keyLocation=KEY_LOCATION_STANDARD,rawCode=0,primaryLevelUnicode=0,scancode=0,extendedKeyCode=0x0'


The puppet does not wait to receive a keyReleased event before calling its ActionListener. In the same run of the program that generated the preceding output, here's the additional output I receive when I click with the mouse a second time on the puppeteer:

Puppeteer Mouse Pressed

Puppet key pressed:
ID=401
KeyCode=32
ParamString='KEY_PRESSED,keyCode=32,keyText=Space,keyChar=' ',keyLocation=KEY_LOCATION_STANDARD,rawCode=0,primaryLevelUnicode=0,scancode=0,extendedKeyCode=0x0'

Puppeteer Mouse Released

Puppet key released:
ID=402
KeyCode=32
ParamString='KEY_RELEASED,keyCode=32,keyText=Space,keyChar=' ',keyLocation=KEY_LOCATION_STANDARD,rawCode=0,primaryLevelUnicode=0,scancode=0,extendedKeyCode=0x0'

Puppet action performed.


On the second click, the puppet does wait until after it receives a keyReleased event before calling its ActionListener, which is what I had expected it would do on every such click-and-release with the mouse on the puppeteer.

Below is my code.

Can anyone help me understand why it behaves as it does, and not as I have outlined in my expectations?


 
Stevens Miller
Bartender
Posts: 1422
29
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah, I think it has to do with the focus. If the puppet has received a keyPressed event and then loses the focus, it will call its ActionListener immediately.
 
Stevens Miller
Bartender
Posts: 1422
29
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yup, that was it. Adding this to the Puppets constructor proves it:

Now the puppet never loses the focus as a result of the puppeteer being clicked, so it waits for the keyReleased event before calling its ActionListener.

Amazing how often just stating a problem in full gives one the fresh perspective needed to see how to solve it.
 
Fred Kleinschmidt
Bartender
Posts: 469
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You might want to look at the Robot class.
 
Stevens Miller
Bartender
Posts: 1422
29
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Fred Kleinschmidt wrote:You might want to look at the Robot class.

Hey, that's cool! Thanks for the pointer.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!