KeyListener 随机停止工作。键绑定?

Posted

技术标签:

【中文标题】KeyListener 随机停止工作。键绑定?【英文标题】:KeyListener randomly stops working. KeyBindings? 【发布时间】:2017-03-15 03:40:51 【问题描述】:

我正在使用 RealTutsGML 的教程制作游戏,所以如果你看过他 2013 年的一些旧视频,你会看到这段代码的大纲来自哪里。

(顺便说一下,我对 Java 并不陌生,但我对 AWT 和 Swing 以及所有这些都相当陌生,因为我曾经/现在有时会编写 Minecraft Bukkit/Spigot 插件。我可以理解相当多的Java 常规语言/语法,但 AWT 和 Swing...)

无论如何,我正在使用 KeyAdapter 来控制按键。但是,它一开始可以工作,然后随机停止工作。我调试过了,好像不是游戏中的对象,是KeyAdapter。我已经查找了一些其他解决方案,人们说它失去了焦点或其他东西,我应该使用 KeyBindings 代替。这很奇怪,因为 KeyListener RANDOMLY 停止为我工作。

无论如何,这是我正在使用的代码:

Handler handler;

public KeyInput(Handler handler)
    this.handler = handler;





public void keyPressed(KeyEvent e)
    int key = e.getKeyCode();

    for (int i = 0; i < handler.object.size(); i++)
        GameObject tempObject = handler.object.get(i);

        if (tempObject.getId() == ObjectId.Player)
            if (key == KeyEvent.VK_SPACE && !tempObject.isJumping())
                tempObject.setJumping(true);
                tempObject.setVelY(-10);
            

            if (key == KeyEvent.VK_Y)
                tempObject.setY(100);
            

            if (key == KeyEvent.VK_A)
                System.out.println("Pressed A");
                tempObject.setVelX(-5);
            
            if (key == KeyEvent.VK_D)
                System.out.println("Pressed D");

                tempObject.setVelX(5);
            

        
    


public void keyReleased(KeyEvent e) 

    int key = e.getKeyCode();

    for (int i = 0; i < handler.object.size(); i++) 

        GameObject tempObject = handler.object.get(i);

        if (tempObject.getId() == ObjectId.Player) 



            if (key == KeyEvent.VK_D) 
                for (int velX = (int) tempObject.getVelX(); velX >= 0; velX--) 
                    tempObject.setVelX(velX);
                
            
            if (key == KeyEvent.VK_A) 
                for (int velX = (int) tempObject.getVelX(); velX <= 0; velX++) 
                    tempObject.setVelX(velX);
                
            
        
    

如您所见,我正在使用 KeyAdapter 来执行此操作。这是我在主类中的初始化方法:

private void init()
    WIDTH = getWidth();
    HEIGHT = getHeight();
    handler = new Handler();
    handler.addObject(new Player(100, 100, handler, ObjectId.Player));
    handler.createTestLevel();

    this.addKeyListener(new KeyInput(handler));


init 方法在 "this.requestFocusInWindow()" 之前被调用

我查阅了一些相关信息,发现 KeyBindings 可以解决其他人的问题。但是,我认为您必须向 JComponents 添加键绑定,而我不知道如何在游戏中获得其中之一。 new JComponent() 不起作用,我的 JFrame 正在添加我的主类(我相信它充当组件,而不是 JComponent)。

如果有人可以提供帮助,那就太好了!谢谢!

编辑#1:

我切换到 KeyBindings!这是 KeyInput 类:

Handler handler;

public JComponent component;

public KeyInput(Handler handler, JComponent component)
    this.handler = handler;
    this.component = component;

    register();


public void register()
    Actions actions = new Actions();

    component.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressSpace");
    component.getActionMap().put("pressSpace", actions.pressSpace());

    component.getInputMap().put(KeyStroke.getKeyStroke("A"), "pressLeft");
    component.getActionMap().put("pressLeft", actions.pressLeft());
    component.getInputMap().put(KeyStroke.getKeyStroke("released A"), "releaseLeft");
    component.getActionMap().put("releaseLeft", actions.releaseXMovement());

    component.getInputMap().put(KeyStroke.getKeyStroke("D"), "pressRight");
    component.getActionMap().put("pressRight", actions.pressRight());
    component.getInputMap().put(KeyStroke.getKeyStroke("released D"), "releaseRight");
    component.getActionMap().put("releaseRight", actions.releaseXMovement());


public JComponent finish()
    return component;



public class Actions

    public Actions()  

    public Action pressRight()
        Action action = new AbstractAction()
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) 
                for (int i = 0; i < handler.object.size(); i++)
                    GameObject temp = handler.object.get(i);
                    if (temp.getId() == ObjectId.Player)
                        temp.setVelX(5);
                        System.out.println("pressed right debug");
                    
                
            

        ;
        return action;
    

    public Action releaseXMovement()
        Action action = new AbstractAction()
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) 
                for (int i = 0; i < handler.object.size(); i++)
                    GameObject temp = handler.object.get(i);
                    if (temp.getId() == ObjectId.Player)
                        temp.setVelX(0);
                    
                
            

        ;
        return action;
    
    public Action pressLeft()
        Action action = new AbstractAction()
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) 
                for (int i = 0; i < handler.object.size(); i++)
                    GameObject temp = handler.object.get(i);
                    if (temp.getId() == ObjectId.Player)
                        temp.setVelX(-5);
                    
                
            

        ;
        return action;
    

    public Action pressSpace()
        Action action = new AbstractAction()
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) 
                for (int i = 0; i < handler.object.size(); i++)
                    GameObject temp = handler.object.get(i);
                    if (temp.getId() == ObjectId.Player)
                        if (!temp.isJumping())
                            temp.setJumping(true);
                            temp.setVelY(-10);
                        
                    
                
            

        ;
        return action;
    


但是,我仍然遇到同样的冻结问题。调试消息不会被发送,这意味着它与我的 setVel 方法没有任何关系。我不知道为什么监听器停止工作...... (起初它可以工作,但随着我不断按键,它最终会停止)。

这是我获得 JComponent 的方式:

JComponent comp = (JComponent) frame.getContentPane();
    KeyInput input = new KeyInput(handler, comp);
    frame.add(input.finish());

【问题讨论】:

如果您需要更具体的帮助,那么根据我的回答,您需要创建并发布有效的minimal reproducible example 作为对当前问题的编辑。与往常一样,代码应该以代码格式的文本而不是链接形式发布。 查看编辑以回答您问题的底部。同样,MCVE 的帮助是不可估量的。 @HovercraftFullOfEels 不在链接中是什么意思?我的帖子中没有任何链接。 【参考方案1】:

它不会“随机”停止工作。相反,它可能(如果没有您的有效MCVE,我们无法确定)在收听的组件不再具有焦点时停止工作。选择是创建一个 kludge 以强制关注组件(坏)或使用键绑定(好)。

关于:

我查阅了一些相关信息,发现 KeyBindings 可以解决其他人的问题。但是,我认为您必须向 JComponents 添加键绑定,而我不知道如何在游戏中获得其中之一。 new JComponent() 不起作用,我的 JFrame 正在添加我的主类(我相信它充当组件,而不是 JComponent)。

您的 GUI 充满了 JComponents,从 JFrame 的 contentPane 开始,一直到您要编程的任何其他 GUI 组件——请记住,大多数 所有 Swing 组件都从 JComponent 扩展而来,并且这些是添加绑定的有效组件。您可能会将其添加到 GUI 的主 JPanel 或 JComponent 中。

【讨论】:

好的!我使用 KeyBindings 并编辑了上面的帖子以显示我所做的更改。但是,我仍然遇到冻结问题。 @Blockhead7360:我无法编译和运行您发布的代码。如果您仍然遇到问题,请考虑创建并发布有效的minimal reproducible example。这是一个 small 可编译和可运行的程序,在您的问题中以代码格式文本(不在链接中)的形式发布,向我们展示了您的问题。祝你好运!

以上是关于KeyListener 随机停止工作。键绑定?的主要内容,如果未能解决你的问题,请参考以下文章

单击按钮后keylistener不起作用

Java KeyListener 口吃

应用程序随机停止接收按键(CGEventTaps)

Java KeyListener 与键绑定

mciSendString 随机停止工作

Django登录随机停止工作