Zistack Zistack - 9 days ago 6
Java Question

KeyEventDispatcher works in one application, but not another

I have on one hand a complex, multi-threaded application, and on the other a single threaded test application that I was hoping to use to debug the first one. I am trying to use A

KeyEventDispatcher
as a
keylistener
of sorts, but no matter how hard I try, I cannot get the
dispatchKeyEvent
to fire in the larger application, yet the smaller application worked on the first try, and they both use the same
KeyEventDispatcher
class. I have scourged the Internet for a solution, or at least an explanation, but I've found basically nothing.

Here's the code for the smaller application:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import zistack.AoD.*;

public class KeyEventDispatcherTest extends JFrame implements Runnable{

static KeyEventDispatcherTest test;
BufferedImage buffer;
Graphics2D g2d;
AoDKeyboard ked;
boolean b = false;

public KeyEventDispatcherTest(){

this.setDefaultCloseOperation(EXIT_ON_CLOSE);
buffer = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
g2d = buffer.createGraphics();
ked = new AoDKeyboard();
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(ked);
new Thread(this).start();

}

public static void main(String[] args){

test = new KeyEventDispatcherTest();

}

public void run() {

g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, 500, 500);
this.repaint();
this.setSize(500, 500);
this.setVisible(true);

while(true){

this.repaint();
try{
Thread.sleep(20);
}
catch(InterruptedException e){
e.printStackTrace();
}

}

}

public void paint(Graphics g){

g.drawImage(buffer, 0, 0, null);
g.setColor(Color.CYAN);
g.drawString("" + ked.test, 0, 0);
for(int i = 0; i < ked.keypressed.length; i++) g.drawString("" + ked.keypressed[i], 0 + ((i % 5) * 100), 15 + ((i / 5) * 15));

}

}


Here's the code for the
KeyEventDispatcher(AoDKeyboard)
class:

package zistack.AoD;

import java.awt.*;
import java.awt.event.*;

public class AoDKeyboard implements KeyEventDispatcher{

public final int[] keycode = {KeyEvent.VK_0, KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_3, KeyEvent.VK_4, KeyEvent.VK_5,
KeyEvent.VK_6, KeyEvent.VK_7, KeyEvent.VK_8, KeyEvent.VK_9, KeyEvent.VK_A, KeyEvent.VK_B, KeyEvent.VK_C,
KeyEvent.VK_D, KeyEvent.VK_E, KeyEvent.VK_F, KeyEvent.VK_G, KeyEvent.VK_H, KeyEvent.VK_I, KeyEvent.VK_J,
KeyEvent.VK_K, KeyEvent.VK_L, KeyEvent.VK_M, KeyEvent.VK_N, KeyEvent.VK_O, KeyEvent.VK_P, KeyEvent.VK_Q,
KeyEvent.VK_R, KeyEvent.VK_S, KeyEvent.VK_T, KeyEvent.VK_U, KeyEvent.VK_V, KeyEvent.VK_W, KeyEvent.VK_X,
KeyEvent.VK_Y, KeyEvent.VK_Z, KeyEvent.VK_UP, KeyEvent.VK_DOWN, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT,
KeyEvent.VK_F1, KeyEvent.VK_F2, KeyEvent.VK_F3, KeyEvent.VK_F4, KeyEvent.VK_F5, KeyEvent.VK_F6, KeyEvent.VK_F7,
KeyEvent.VK_F8, KeyEvent.VK_F9, KeyEvent.VK_F10, KeyEvent.VK_F11, KeyEvent.VK_F12};
public boolean[] keypressed = new boolean[keycode.length];

public boolean test = false;

public AoDKeyboard(){

for(int i = 0; i < keypressed.length; i++) keypressed[i] = false;

}

public boolean dispatchKeyEvent(KeyEvent e){

if(e.getID() == e.KEY_PRESSED) for(int i = 0; i < keycode.length; i++) if(e.getKeyCode() == keycode[i]) keypressed[i] = true;

if(e.getID() == e.KEY_RELEASED) for(int i = 0; i < keycode.length; i++) if(e.getKeyCode() == keycode[i]) keypressed[i] = false;

test = true;
return false;

}

}


And finally, here's a portion of the large application's code that contains the
KeyEventDispatcher
that doesn't work:

package zistack.AoD;

import zistack.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.Vector;

public class AoDGraphicUpdater implements Runnable{

KeyboardFocusManager keymanager;
BufferedImage backbuffer;
Graphics2D g2d;
protected Vector gameobjects;
protected GameWindow gwindow;
protected Thread updater;
protected long timer = 0;
protected int fademode, fadealpha;
public final int DARK = 0, FADE_TO_CLEAR = 1, CLEAR = 2, FADE_TO_DARK = 3;

AoDKeyboard keyboard;//////////////create keydispatcher

public AoDGraphicUpdater(Vector v, GameWindow gw){

keyboard = new AoDKeyboard();///////////
keymanager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
keymanager.addKeyEventDispatcher(keyboard);//////////add dispatcher to qeue
gameobjects = v;
gwindow = gw;
backbuffer = new BufferedImage(gwindow.getWidth(), gwindow.getHeight(), BufferedImage.TYPE_INT_RGB);
g2d = backbuffer.createGraphics();
g2d.setComposite(AlphaComposite.SrcOver);
fademode = DARK;
fadealpha = 255;
updater = new Thread(this);
updater.start();

}

public void run(){

g2d.setFont(new Font("Dialog", Font.PLAIN, 10));
while(true){
wipeScreen(g2d);
g2d.setColor(Color.CYAN);

//UPDATE OBJECTS

((GameView)gameobjects.firstElement()).update();
((AoDMenuHandler)gameobjects.elementAt(2)).update();

//DRAW OBJECTS

if(fadeMode() != DARK){
//draw anything under fade layer
((AoDSpaceGenerator)gameobjects.elementAt(1)).graphicUpdate(g2d);

}

if(fadeMode() == FADE_TO_CLEAR){
g2d.setColor(new Color(0, 0, 0, fadeAlpha()));
g2d.fillRect(0, 0, backbuffer.getWidth(), backbuffer.getHeight());
setFadeAlpha(fadeAlpha() - 15);
if(fadeAlpha() <= 0)setFadeMode(CLEAR);
}
else if(fadeMode() == FADE_TO_DARK){
g2d.setColor(new Color(0, 0, 0, fadeAlpha()));
g2d.fillRect(0, 0, backbuffer.getWidth(), backbuffer.getHeight());
setFadeAlpha(fadeAlpha() + 15);
if(fadeAlpha() >= 255)setFadeMode(DARK);
}

//draw anything on top of the fade layer
((AoDMenuHandler)gameobjects.elementAt(2)).graphicUpdate(g2d);


///////////////////////////DEBUG DISPLAY///////////////////////////////
//g2d.drawString("Debug2: " + blah, 100, 150);
g2d.drawString("" + keyboard.test, 100, 100);//draws whether or not the method has fired to the screen
g2d.drawString("" + keymanager, 100, 125);

while(timer > System.currentTimeMillis());
timer = System.currentTimeMillis() + 20;
gwindow.setBuffer(backbuffer);

}

}

public void setFadeMode(int mode){

this.fademode = mode;
if(fadeMode() == DARK)setFadeAlpha(255);
if(fadeMode() == CLEAR)setFadeAlpha(0);

}

public void setFadeAlpha(int b){

this.fadealpha = b;

}

public int fadeMode(){

return fademode;

}

public int fadeAlpha(){

return fadealpha;

}

protected void wipeScreen(Graphics2D g2d){

g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, gwindow.getWidth(), gwindow.getHeight());

}

}


Something interesting also happens when I run the larger application; any keys I press are typed into my compiler(eclipse), as if my keyboard focus were on the compiler the entire time.

Right now my best guess as to the problem is that the
KeyEventDispatcher
is being added too far down the queue, so that any keyevents are handled by the time they get to my dispatcher, but I could be totally wrong. I guess my question is, why does
KeyEventDispatcher
work in one application and not another, and how can I get it to work in both?

Answer

So I eventually figured out that, because I was using an owner-less JWindow, my program could not grab the keyboard focus, thus not having any events to dispatch. Switching to an undecorated JFrame did the trick.

Zistack