複雑なマルチスレッド アプリケーションと、最初のアプリケーションのデバッグに使用したいと考えていたシングル スレッド テスト アプリケーションがあります。A を一種として使用しようとしていますKeyEventDispatcher
がkeylistener
、どんなに頑張ってもdispatchKeyEvent
、より大きなアプリケーションで を起動することはできませんが、小さなアプリケーションは最初の試行で機能し、両方とも同じKeyEventDispatcher
クラスを使用します。解決策、または少なくとも説明を求めてインターネットを探しましたが、基本的に何も見つかりませんでした。
小さいアプリケーションのコードは次のとおりです。
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));
}
}
KeyEventDispatcher(AoDKeyboard)
クラスのコードは次のとおりです。
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;
}
}
KeyEventDispatcher
最後に、動作しないを含む大規模なアプリケーションのコードの一部を次に示します。
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());
}
}
大規模なアプリケーションを実行すると、興味深いことが起こります。押したキーはすべて、コンパイラー (eclipse) に入力されます。キーボードのフォーカスがずっとコンパイラーにあったかのようです。
今のところ、問題についての私の最善の推測は、KeyEventDispatcher
キーイベントがディスパッチャーに到達するまでに処理されるように、キューのはるか下に追加されていることですが、完全に間違っている可能性があります。私の質問は、なぜKeyEventDispatcher
あるアプリケーションで動作し、別のアプリケーションでは動作しないのか、そしてどうすれば両方で動作させることができるのでしょうか?