1

私は問題に取り組んでいますが、Japplet の JComponent サブコンポーネントに焦点を当てることができないようです。キーボード リスナーを使用して多数の画面上の要素 (ゲーム) のキー押下を登録できるように、コンポーネントにフォーカスする必要があります。

コードは次のとおりです。

class TestApplet extends JApplet { 
    public void init(){ 
        setSize(400, 800); 
        new test class();
        setFocusable(true);
        setVisible(true);
    }
}


 public class testclass extends JPanel {
 public testclass() {
        grabFocus();
        requestFocus();
        requestFocusInWindow();

       System.out.println("visible: " + isVisible());
        System.out.println("Enbled " + isEnabled());
        System.out.println("Focusable " + isFocusable()); 
        System.out.println(isFocusOwner()); 
    } 
}

出力は次のように評価されます

visible: true
Enbled true
Focusable true
false

これは、サブコンポーネントのフォーカス グラブのすべての可能な組み合わせを使用したという事実にもかかわらずです。同じコードを Japplet に配置すると、作成したキーボード リスナーは機能しますが、サブコンポーネントを使用すると機能しません...

階層的なトポグラフィーに多くの JPanel があるため、これは私のアプリケーションにとって非常に重要です。

NB これは macosx 固有のバグである可能性があることが示唆されています - 私は Intellij CE11.1 を使用しています。私はこれを確認することはできませんが。

更新: プログラムが mb1,2 とマウスの中央ボタンに応答する機能も作成する必要があります。明らかに、これはフォーカスなしでは不可能ですか?

4

1 に答える 1

2

私は独自の SSCCE を作成しました。テストでは、使用する手法に関係なく、アプレットが機能するためには、アプレットが要求してフォーカスを取得する必要があるようです。これは、xxx ミリ秒後にフォーカスを要求する javax.swing.Timer を含む 2 つのクラッジのいずれかを使用して、私の Windows システムで正常に動作するようにpaint(...)なりました。アプレットがちょうどレンダリングされているとき)。たとえば、両方の kludges (必要なのは 1 つだけ) と、キー バインディングと SSCCE の例を示します。

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.lang.reflect.InvocationTargetException;

import javax.swing.*;

@SuppressWarnings("serial")
public class KeyBindingEg extends JApplet {
   protected static final int TIMER_DELAY = 100;
   private boolean firstPane = true;

   @Override
   public void init() {
      createAndShowGui();
   }

   private void createAndShowGui() {
      try {
         SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
               TestClass test = new TestClass();
               getContentPane().add(test);

               // a kludge to get focus on the GUI some time after it has been created
               new Timer(TIMER_DELAY, new ActionListener() {

                  @Override
                  public void actionPerformed(ActionEvent e) {
                     requestFocusInWindow();
                     ((Timer)e.getSource()).stop();
                  }
               }).start();
            }
         });
      } catch (InterruptedException e) {
         e.printStackTrace();
      } catch (InvocationTargetException e) {
         e.printStackTrace();
      }
   }

   @Override
   public void paint(Graphics g) {
      super.paint(g);
      // another kludge to get focus on the GUI after it is
      // first rendered
      if (firstPane) {
         requestFocusInWindow();
         firstPane = false;
      }
   }
}

@SuppressWarnings("serial")
class TestClass extends JPanel {
   public TestClass() {
      setLayout(new BorderLayout());
      add(new JLabel("TestClass", SwingUtilities.CENTER));

      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      for (KeyInfo keyInfo : KeyInfo.values()) {
         KeyStroke keyStroke = KeyStroke.getKeyStroke(keyInfo.getKeyCode(), 0);
         inputMap.put(keyStroke , keyInfo.toString());
         actionMap.put(keyInfo.toString(), new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent evt) {
               System.out.println("key press: " + evt.getActionCommand());
            }
         });
      }
   }
}

enum KeyInfo {
   UP(KeyEvent.VK_W), DOWN(KeyEvent.VK_S), LEFT(KeyEvent.VK_A), RIGHT(KeyEvent.VK_D);
   private int keyCode;

   private KeyInfo(int keyCode) {
      this.keyCode = keyCode;
   }

   public int getKeyCode() {
      return keyCode;            
   }

}

AncestorListener を使用した上記のコード:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;

import javax.swing.*;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

@SuppressWarnings("serial")
public class KeyBindingEg extends JApplet {
   protected static final int TIMER_DELAY = 100;
   private boolean firstPane = true;

   @Override
   public void init() {
      createAndShowGui();
   }

   private void createAndShowGui() {
      try {
         SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
               TestClass test = new TestClass();

               JPanel contentPane = (JPanel) getContentPane();
               contentPane.add(test);
               contentPane.addAncestorListener(new RequestFocusListener());               
            }
         });
      } catch (InterruptedException e) {
         e.printStackTrace();
      } catch (InvocationTargetException e) {
         e.printStackTrace();
      }
   }

}

class RequestFocusListener implements AncestorListener {
   public void ancestorRemoved(AncestorEvent arg0) {}
   public void ancestorMoved(AncestorEvent arg0) {}

   @Override
   public void ancestorAdded(AncestorEvent aEvt) {
      Component comp = (Component) aEvt.getSource();
      comp.requestFocusInWindow();
   }

}

@SuppressWarnings("serial")
class TestClass extends JPanel {
   public TestClass() {
      setLayout(new BorderLayout());
      add(new JLabel("TestClass", SwingUtilities.CENTER));

      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      for (KeyInfo keyInfo : KeyInfo.values()) {
         KeyStroke keyStroke = KeyStroke.getKeyStroke(keyInfo.getKeyCode(), 0);
         inputMap.put(keyStroke, keyInfo.toString());
         actionMap.put(keyInfo.toString(), new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent evt) {
               System.out.println("key press: " + evt.getActionCommand());
            }
         });
      }
   }
}

enum KeyInfo {
   UP(KeyEvent.VK_W), DOWN(KeyEvent.VK_S), LEFT(KeyEvent.VK_A), RIGHT(
         KeyEvent.VK_D);
   private int keyCode;

   private KeyInfo(int keyCode) {
      this.keyCode = keyCode;
   }

   public int getKeyCode() {
      return keyCode;
   }

}
于 2012-12-01T21:49:01.900 に答える