【问题标题】:Java Applet Game Design : Keyboard focusJava Applet 游戏设计:键盘焦点
【发布时间】:2012-08-25 13:14:39
【问题描述】:

我在错误的地方 (GameDev) 发布了此内容,但没有得到任何回复。所以我在这里再次发布。

我正在制作一个小程序游戏,它正在渲染,游戏循环正在运行,动画正在更新,但键盘输入不起作用。这是一个 SSCCE。

public class Game extends JApplet implements Runnable {

    public void init(){
        // Initialize the game when called by browser
        setFocusable(true);
        requestFocus();
        requestFocusInWindow();  // Always returning false
        GInput.install(this);    // Install the input manager for this class
        new Thread(this).start();
    }

    public void run(){
        startGameLoop();
    }

}

这是 GInput 类。

public class GInput implements KeyListener {

    public static void install(Component c){
        new GInput(c);
    }

    public GInput(Component c){
        c.addKeyListener(this);
    }

    public void keyPressed(KeyEvent e){
        System.out.println("A key has been pressed");
    }

    ......

}

这是我的 GInput 类。当作为小程序运行时,它不起作用,当我将 Game 类添加到框架时,它可以正常工作。

谢谢

现在解决了。查看我的解决方案

【问题讨论】:

  • 由于它作为框架工作,最好的方法是使用Java Web Start从链接启动框架。
  • 我不做小程序,所以我不能确定问题出在哪里,但是您可以通过使用键绑定而不是 KeyListener 来解决焦点问题。此外,您的 SSCCE 不符合 SSCCE 规范。我们不能运行它也不能测试它。
  • 我知道我可以通过 web start 做到这一点,但我不想学习作为小程序进行编程,因为这将在我的游戏引擎中进行
  • 我认为大多数人更愿意看到合规的 sscce。

标签: java swing applet keyboard focus


【解决方案1】:

一种可能的解决方案是使用 JApplet 的 contentPane,将焦点设置在它而不是 JApplet 本身上。但我的偏好是改用键绑定。您可能需要使用 Swing Timer 才能工作:

我的 SSCCE:

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;

import javax.swing.*;

@SuppressWarnings("serial")
public class AppletKeyListen extends JApplet {
   @Override
   public void init() {
      try {
         SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
               setFocusable(true);

               int timerDelay = 100;
               Timer myTimer = new Timer(timerDelay , new ActionListener() {

                  @Override
                  public void actionPerformed(ActionEvent arg0) {
                     boolean focusObtained = requestFocusInWindow();
                     System.out.println("focusObtained for JApplet: " + focusObtained);

                     Container contentPane = getContentPane();
                     contentPane.setFocusable(true);

                     focusObtained = contentPane.requestFocusInWindow();
                     System.out.println("focusObtained for contentPane: " + focusObtained);


                  }
               });
               myTimer.setRepeats(false);
               myTimer.start();
//               boolean focusObtained = requestFocusInWindow();
//               System.out.println("focusObtained: " + focusObtained);
//               
//               Container contentPane = getContentPane();
//               contentPane.setFocusable(true);
//               
//               focusObtained = contentPane.requestFocusInWindow();
//               System.out.println("focusObtained: " + focusObtained);

            }
         });
      } catch (InvocationTargetException | InterruptedException e) {
         e.printStackTrace();
      }
   }
}

【讨论】:

  • 但是游戏本身是在 JApplet 中编程的。如何使用内容窗格?你能解释一下吗..
  • @SriHarshaChilakapati:查看编辑和代码,,这就是键绑定最佳工作的地方。
  • 但经常有人告诉我们,计时器对于游戏来说是一个糟糕的实现。还有其他方法吗..请
  • @sri:WTF?这个“规则”是从哪里来的?太疯狂了。我认为你的问题令人困惑,因为这与你所说的游戏循环无关。
  • @SriHarshaChilakapati 如果您仔细查看发布的代码,您会发现在这种情况下,Timer 仅用于在事件调度线程稍有延迟后执行某些代码。这与使用Timer 更新游戏状态无关
【解决方案2】:

如果您在浏览器中运行,您可能需要单击小程序以使其获得焦点。出于安全原因,大多数浏览器不会让小程序在用户不点击的情况下直接获取键盘焦点。

所以,我会添加一个鼠标侦听器,而不是直接在 init() 中进行焦点抓取:

addMouseListener(new MouseAdapter() {
   public void onMousePress(MouseEvent e) {
      requestFocus();
   }
});

【讨论】:

  • 如果小程序没有焦点,不是出于安全原因。
  • 我只包含了类的基本模板。完整的 GInput 类可以在这里找到。 code.google.com/p/game-engine-for-java/source/browse/src/com/…
  • 也尝试使用焦点监听器,但仍然没有解决方案:(
  • 好的,但请注意您的鼠标侦听器不请求焦点。我一直发现,要获得小程序的关键焦点,我需要让它以“点击开始”消息开头,然后让用户实际点击它。
【解决方案3】:

现在我有两个选择,

  • 使用 JWS
  • 不要制作小程序模式

现在我尝试创建一个名为GApplet 的新类。它将游戏加载到一个新的 JFrame 中,该 JFrame 可以从 applet 运行。现在我也可以从网络访问全屏模式。这是课程的链接。

The GApplet class

现在它就像 webstart 一样工作,实际上是一个小程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2014-04-22
    相关资源
    最近更新 更多