Sub JComponent尽管可见,但无法获得焦点

时间:2012-12-01 16:09:16

标签: java focus japplet

我正在解决一个问题,我似乎无法专注于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。

N.B有人建议这可能是一个特定于macosx的bug - 我正在使用Intellij CE11.1。虽然我无法验证这一点。

更新:我还必须创建程序应该响应mb1,2和鼠标中键的功能 - 显然,如果没有焦点,这是不可能的?

1 个答案:

答案 0 :(得分:2)

我创建了自己的SSCCE并且在测试时,似乎无论使用什么技术,applet仍然必须请求并获得他们的工作焦点。我已经使用两个kludges中的任何一个成功地在我的Windows系统上工作,包括在xxx ms之后请求焦点的javax.swing.Timer,或者覆盖第一次请求焦点的JApplet的paint(...)方法调用paint(以及刚刚渲染applet时)。例如,显示两个kludges(只需要一个)和一个键绑定和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;
   }

}