1

我有2节课。

一个扩展画布并在内部创建一个 jframe 并将画布添加到该 jframe 并添加另一个 keyadapter 类来接收关键事件。我也有测试代码的主要功能。从 main 运行时,会显示表单并接收关键事件。

现在我创建了另一个扩展 jframe 并实现 keylistener 以接收这种形式的事件的类。

在第二类中完成功能后,我想关闭第二个表单并显示第一个表单。当从第二类的键事件函数中显示它时,第一类键侦听器不起作用。

请看一下我的代码并告诉我如何纠正我的问题。感谢您的宝贵时间和宝贵建议。

1级

public class Test extends Canvas {

private JFrame container;

public Test() {

    container = new JFrame("Space Invaders");
    JPanel panel = (JPanel) container.getContentPane();
    panel.setPreferredSize(new Dimension(screenSize.width, screenSize.height));
    panel.setLayout(null);
    setBounds(0, 0, screenSize.width, screenSize.height);
    panel.add(this);
    container.pack();
    container.setResizable(false);
    container.setVisible(true);

    try {

        addKeyListener(new KeyInputHandler(this));
    } catch (Exception e) {
        e.printStackTrace();
    }
    requestFocus();
}

private class KeyInputHandler extends KeyAdapter {

public void keyPressed(KeyEvent e) {
    //Some Action
}
public void keyReleased(KeyEvent e) {
    //Some Action
}
public void keyTyped(KeyEvent e) {
    //Some Action
}
}

public static void main(String args[]){
    //Running this canvas here works perfectly with all added keylisteners
}
}

2 级

public class Sample extends JFrame implements KeyListener {

public Sample() {
    init();
    this.setSize(100, 100);
    this.setVisible(true);
    Sample.this.dispose();
            // Created a window here and doing some operation and finally redirecting
            // to the previous test window. Even now the test window works perfectly
            // with all keylisteners
    new Test();
}

public static void main(String[] args) {
    new Sample();

}

private void init() {
    addKeyListener(this);
}

@Override
public void keyTyped(KeyEvent e) {

}

@Override
public void keyPressed(KeyEvent e) {
    removeKeyListener(this);
    Sample.this.dispose();
            // But when calling the previous Test window here, the window 
            // gets displayed but the keylistener is not added to the 
            // window. No keys are detected in test window.
    new Test();
}

@Override
public void keyReleased(KeyEvent e) {

}
}
4

1 回答 1

5

简单的不要使用KeyListener/KeyAdapter那是用于 AWT 组件并且在与 Swing 一起使用时已知焦点问题。

这些问题可以通过确保您的组件是可聚焦的,setFocusable(true)而不是requestFocusInWindow()在组件添加/可见后调用来解决。

而是将KeyBindings用于 Swing。

例如说现在我们想监听D按下和释放:

public static void addKeyBindings(JComponent jc) {
    jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), "D pressed");
    jc.getActionMap().put("D pressed", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            System.out.println("D pressed");
        }
    });

    jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true), "D released");
    jc.getActionMap().put("D released", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            System.out.println("D released");
        }
    });
}

我们会这样称呼这个方法:

JPanel ourPanel=new JPanel();

...

addKeyBindings(ourPanel);//adds keybindings to the panel

其他代码建议

  • Event Dispatch Thread始终通过SwingUtilities.invokeLater(Runnable r)块创建和操作 Swing 组件

  • JFrame不要不必要地扩展课程

  • 不要在类上实现接口,除非该类将用于该目的,或者其他类需要访问接口方法。

  • 正如@AndrewThompson 所提到的,不要使用多个JFrames,要么将其余部分交换为JDialog,要么使用CardLayout. 有关示例,请参见此处。

于 2013-01-13T16:43:10.667 回答