0

我写了一些应用程序并想向它添加一些键盘输入。我的主类扩展了一个 JPanel,所以我可以将 keyAdapter 添加到构造函数中。keyAdapter 是一个名为“InputAdapter”的新类,它通过 keyPressed() 和 keyReleased() 方法扩展了 keyadapter。单击或释放控制台应打印一些字符串,例如此处的“测试”

我不知道为什么,但控制台不会打印任何文本。此外,当我告诉它将精灵可见性变为 false 时,也没有任何反应。

所以我猜 KeyAdapter 不能正常工作,所以有人可以仔细看看我的代码行吗?

我想这个问题与我编写的其他实现的类无关,因为当删除它们时,键盘输入无效的问题仍然存在。

包 com.ochs.game;

public class Game extends JPanel implements Runnable{
private static final long serialVersionUID = 1L;

public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 3;

public boolean isRunning;

public Game() {
    addKeyListener(new InputAdapter());
    setFocusable(true);
    requestFocus();
    start();
}

public void start() {
    isRunning = true;
    new Thread(this).start();
}

public void stop() {
    isRunning = false;
}

public void run() {
    init();
    while(isRunning) {

        update();
        repaint();

        try {
            Thread.sleep(5);
        } catch (InterruptedException e) {
            System.out.println("Thread sleep failed.");
        }
    }
}

public void init() {

}

public void update() {

}

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D)g;

}

public static void main(String[] args) {
    Game gameComponent = new Game();
    Dimension size = new Dimension(WIDTH*SCALE, HEIGHT*SCALE);

    JFrame frame = new JFrame("Invaders");
    frame.setVisible(true);
    frame.setSize(size);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.add(gameComponent);
}
public class InputAdapter extends KeyAdapter {

    @Override
    public void keyPressed(KeyEvent arg0) {
        System.out.println("Test");
    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        System.out.println("Test");
    }


}
}   
4

3 回答 3

1

您的基本代码设计是旧的 AWT 绘画代码。为了更好的 Swing 设计,我赞同 MadProgrammer 所说的一切。

此外:

  1. 不需要空的 init() 方法。摆脱方法和对方法的调用。
  2. update() 方法也一样。

发布代码的最大问题是您在框架可见之后将面板添加到框架中。在使框架可见之前,您应该始终将组件添加到框架:

JFrame frame = new JFrame("Invaders");
frame.add(gameComponent);
...
frame.setVisible(true);

不要采取简单的方法,只需进行上述更改即可。为 Swing 程序而不是 AWT 程序编写代码。

于 2013-08-19T22:07:43.697 回答
1

您的代码对我有用:

java version "1.6.0_27"
OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1ubuntu0.12.04.2)
OpenJDK Client VM (build 20.0-b12, mixed mode, sharing)

提示 1 - 我猜你应该覆盖paintComponent(Graphics g),而不是paint()

public void paintComponent(Graphics g){

    super.paintComponent(g);
    //...
}

提示 2 -在您的 JPanel 上使用addNotify() :

public void addNotify(){

    super.addNotify();
    //start from here
    new Thread(this).start();
}

提示 3 - 从 EDT 线程以这种方式启动您的应用程序(请参阅SwingUtilities.invokeLater 做什么?

SwingUtilities.invokeLater(new Runnable() {

    public void run(){

    //your code

   }
});

希望能帮助到你!

于 2013-08-19T20:48:15.600 回答
1

这可能不起作用的原因有很多。 KeyListener很挑剔。它要求注册的组件不仅是可聚焦的,而且是有焦点的。

即使您的组件似乎同时具备这两种功能,但如果由于某种原因,焦点被另一个组件抓住,则该组件KeyListener将停止工作。

您应该使用requestFocusInWindow并且requestFocus不可靠,但更好的解决方案是使用Key bindings,它能够通过焦点克服所有混乱......

您应该避免覆盖paintpaintComponent改为使用,请查看执行自定义绘画以获取更多详细信息。

使用 Swing 混合线程很棘手,您还需要确保在更新状态时没有违反 Swing 的单线程规则。查看Swing 中的并发以获取更多详细信息

于 2013-08-19T21:20:52.237 回答