有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java无键盘输入工作键适配器

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

我不知道为什么,但控制台不会打印任何文本。此外,当我告诉它将精灵可见性设置为false时,也不会发生任何事情

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

我想这个问题与我编写的其他实现类没有任何关系,因为当删除它们时,非工作键盘输入的问题仍然存在

包com。奥克斯。游戏

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");
    }


}
}   

共 (3) 个答案

  1. # 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(图形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线程以这种方式启动应用程序(请参见What does SwingUtilities.invokeLater do?

    SwingUtilities.invokeLater(new Runnable() {
    
        public void run(){
    
        //your code
    
       }
    });
    

    希望有帮助

  2. # 2 楼答案

    您的基本代码设计是旧的AWT绘制代码。我附和程序员为更好的秋千设计所说的一切

    此外:

    1. 不需要空的init()方法。摆脱该方法和对该方法的调用
    2. update()方法也是如此

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

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

    不要采取简单的方法,只需做出上述改变。为Swing程序而不是AWT程序编写代码

  3. # 3 楼答案

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

    即使您的组件似乎同时满足这两个条件,但如果由于某种原因,焦点被另一个组件抓住,那么KeyListener将停止工作

    你应该使用^{},而requestFocus是不可靠的,但更好的解决方案是使用Key bindings,它有能力通过聚焦克服所有的混乱

    您应该避免覆盖paint,而是使用paintComponent,有关详细信息,请查看Performing Custom Painting

    将线程与Swing混合是很棘手的,您还需要确保在更新状态时没有违反Swing的单线程规则。查看Concurrency in Swing了解更多详细信息