1

私は2つのクラスを持っています。

1 つはキャンバスを拡張し、内部で jframe を作成し、その jframe にキャンバスを追加し、キー イベントを受け取る別のキーアダプター クラスを追加します。コードをテストするためのメイン関数もあります。メインから実行すると、フォームが表示され、重要なイベントも受け取ります。

ここで、jframe を拡張し、keylistener を実装してこの形式でイベントを受信する別のクラスを作成します。

2 番目のクラスで機能が完了したら、2 番目のフォームを閉じて最初のフォームを表示します。2 番目のクラスのキー イベント関数から表示すると、1 番目のクラスのキー リスナーが機能しません。

私のコードをちらっと見て、私の問題を修正する方法を教えてください。あなたの時間と貴重な提案をありがとう.

クラス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()

Swing にはKeyBindingsを使用します。

たとえば、pressed と release をリッスンしたいとします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を介して、常に Swing コンポーネントを作成および操作します。SwingUtilities.invokeLater(Runnable r)

  • JFrame不必要にクラスを拡張しないでください

  • クラスがその目的で使用される場合、または他のクラスがインターフェイス メソッドにアクセスする必要がある場合を除き、クラスにインターフェイスを実装しないでください。

  • @AndrewThompson が述べたように、複数JFrameの s を使用しないでください。残りをJDialogに交換するか、 を使用してCardLayoutください。例については、こちらを参照してください。

于 2013-01-13T16:43:10.667 に答える