java - 关键事件只是有时注册

标签 java swing events keyevent key-events

老实说,我不知道我做错了什么。

有时,关键事件会注册,有时不会。
我的意思是有时当我运行 Frogger2 时我会注册事件,有时什么也没有。

当关键事件注册或不注册时,这似乎完全是随机的。通常,如果我暂时不测试任何东西并运行 Frogger2,事件会注册,当我关闭它并重新运行完全相同的程序时,我不会收到任何事件。

请帮忙。

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class Frogger2 extends JPanel {

public static JFrame frame;
public static Frogger2 F;

public Frogger2() {}

public Dimension getPreferredSize() { return new Dimension(500,500); }
public void paintComponent(Graphics g) { super.paintComponent(g); }


private int fdir;

public void moveLeft() {
    travel(2);
}
public void moveRight() {
    travel(0);
}
public void moveUp() {
    travel(3);
}
public void moveDown() {
    travel(1);
}
private void travel(int ddd) {
    System.out.println(ddd);
}


private boolean step() {
    System.out.println("FDIR: "+fdir);
    return true;
}

public void start() {
    fdir = 2;
    while(true) {
        boolean a = step();
        if (!a) break;
        try {
            Thread.sleep(25);
        } catch(Exception e) {}
    }
}

public static void main(String[] args) {
    frame = new JFrame("Frogger");

    F = new Frogger2();
    F.setDoubleBuffered(true);
    frame.add(F);
    frame.pack();
    frame.setVisible(true);
    frame.setResizable(false);
    JPanel abc = (JPanel)frame.getContentPane();
    abc.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), "left");
    abc.getActionMap().put("left", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {F.moveLeft();}
    });
    abc.getInputMap().put(KeyStroke.getKeyStroke("RIGHT"), "right");
    abc.getActionMap().put("right", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {F.moveRight();}
    });
    abc.getInputMap().put(KeyStroke.getKeyStroke("UP"), "up");
    abc.getActionMap().put("up", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {F.moveUp();}
    });
    abc.getInputMap().put(KeyStroke.getKeyStroke("DOWN"), "down");
    abc.getActionMap().put("down", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {F.moveDown();}
    });

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    F.start();

}

}

最佳答案

这个问题通常发生在焦点在面板上时,每次按下任何键时都必须确保面板在焦点上。
您需要查看 Java 教程以获得对 Key Bindings 的一个很好的概述。作为@camickr在评论中提到它。
另请参阅 question@mKorbel 回答(非常感兴趣的答案)。

Key Bindings 中有趣的事情是:当你按下 Ctrl+Shift+Space 时,程序会执行一些操作,这非常有趣且高度推荐使用 Key Bindings,另见我的 first question on stack 是关于这个主题的。

这是您的代码,我做了一些更改:

  • KeyListener 每次按下一个键,焦点就会在面板上。
  • MouseListener 当鼠标进入面板或鼠标点击面板时,焦点将再次位于面板上。
  • FocusListener:了解面板是否可聚焦。

代码如下:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class MovingJPanel {

    public static void main(String[] args) {
    JFrame frame = new JFrame("Frogger");

    frame.pack();
    frame.setVisible(true);
    frame.setResizable(true);
    frame.setLocationRelativeTo(null);
    frame.setSize(400,400);
    JPanel abc = new JPanel();
    abc.setBackground(Color.CYAN);
    abc.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), "left");
    abc.getActionMap().put("left", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("LEFT");}
    });
    abc.getInputMap().put(KeyStroke.getKeyStroke("RIGHT"), "right");
    abc.getActionMap().put("right", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("ROIGHT");}
    });
    abc.getInputMap().put(KeyStroke.getKeyStroke("UP"), "up");
    abc.getActionMap().put("up", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("UP");}
    });
    abc.getInputMap().put(KeyStroke.getKeyStroke("DOWN"), "down");
    abc.getActionMap().put("down", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("DOWN");}
    });

    abc.addFocusListener(new FocusAdapter() {
        @Override
        public void focusGained(FocusEvent e) {
            System.out.println("Focus Gained");
        }
        @Override
        public void focusLost(FocusEvent e) {
            System.out.println("Focus Lost");
        }  
});
    abc.addKeyListener(new KeyAdapter() {
        @Override
        public void keyTyped(KeyEvent e) {
            JPanel p = (JPanel)e.getSource();
            p.requestFocus();
        } 
});

    abc.addMouseListener(new MouseAdapter() {

        @Override
        public void mouseEntered(MouseEvent e) {
           JPanel p = (JPanel)e.getSource();
            p.requestFocus();
        }

});
    frame.getContentPane().add(abc,"Center");
    frame.getContentPane().add(new JButton("Click Me"),"North");
    abc.requestFocusInWindow();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}
}

关于java - 关键事件只是有时注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16885419/

相关文章:

java - 在此 Java Stream 用法中是否应该调用映射操作?

java - Hibernate和Mysql,事务自动提交只是一个部分

java - 子组件setSize的地方在哪里

java - 如何让圆圈响应计时器?

javascript - 增加 SVG 元素的悬停区域

java - 比较映射和列表时如何将 Java 7 重构为 Java 8

java - statements.executeQuery 中的 NPE

java - 将 JPanel 动态添加到 groupLayout

php - 在处理时区时如何处理全天和定时事件?

c# - 请解释定时器事件异步/等待语法