KeyEventDispatcher在一个应用程序中工作,但不在另一个应用程序中工作

时间:2011-08-05 16:11:46

标签: java multithreading swing keylistener keyevent

我一方面是一个复杂的多线程应用程序,另一方面是我希望用来调试第一个应用程序的单线程测试应用程序。我正在尝试使用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在一个应用程序而不是另一个应用程序中工作,我怎样才能让它在两个应用程序中都有效?

1 个答案:

答案 0 :(得分:0)

所以我最终想通了,因为我使用的是一个没有主人的JWindow,我的程序无法抓住键盘焦点,因此没有任何事件要发送。切换到未修饰的JFrame就可以了。

Zistack