【问题标题】:KeyListener not reacting at allKeyListener 完全没有反应
【发布时间】:2013-05-05 20:39:59
【问题描述】:

我已经尝试解决这个问题大约 5 个小时了,但我就是想不通为什么我的 KeyListener 根本没有反应。它甚至看起来都没有达到寻找keyInput的地步? 这是它被调用的类:

package summonit;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;

public class Player extends KleinerScreen implements KeyListener {

    public Player() throws IOException{
        addKeyListener(this);
    }
    public static int playerX=20;
    public static int playerY;

    @Override
    public void keyTyped(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_K) {
            playerX += 100;
        }
        System.out.println(playerX);
        repaint();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_K) {
            playerX += 100;
        }
        System.out.println(playerX);
        repaint();

    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

}

还有主类:

package summonit;
import java.awt.*;
import java.io.IOException;
import javax.swing.JFrame;

public class Summonit extends JFrame{

    public static void main(String[] args) throws IOException {

        Summonit game = new Summonit();
        Screen window = new Screen();
        TileMap tilemap = new TileMap();
        Player player = new Player();

    }
}

面板类

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package summonit;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

/**
 *
 * @author Boyen
 */
public class KleinerScreen extends JPanel {

    String i = "457528_3569247037775_1427420686_o.jpg";
    String s = "City.txt";
    public static Dimension windowsize = new Dimension(1000, 1000);
    private int mapWidth;
    private int mapHeight;
    public int map[][];
    final int playerRows = 4;
    final int playerCols = 4;
    //images of tiles
    private Image tileYellowPath;
    private Image tileGround;
    BufferedImage bigPlayerImg;
    BufferedImage[] sprites;
    //images

    public KleinerScreen() throws IOException {
        setPreferredSize(windowsize);

        tileYellowPath = new ImageIcon(getClass().getResource("/CorrodedTechnoTiles.png")).getImage();
        tileGround = new ImageIcon(getClass().getResource("/images.jpg")).getImage();
        bigPlayerImg = ImageIO.read(new File("res/sprites_player_3.png"));
        sprites = new BufferedImage[playerRows * playerCols];
        for (int i = 0; i < playerRows; i++) {
            for (int j = 0; j < playerCols; j++) {
                sprites[(i * playerCols) + j] = bigPlayerImg.getSubimage(
                        j * 150,
                        i * 150,
                        150,
                        150);
            }
        }

    }

    public void readTiles() {
    }

    public void paint(Graphics g) {
        for (int i = 0; i < TileMap.map.length; i++) {
            for (int j = 0; j < TileMap.map[i].length; j++) {

                switch (TileMap.map[i][j]) {
                    case 0:
                        g.drawImage(tileGround, windowsize.width / 10 * j, windowsize.height / 10 * i, windowsize.height / 10, windowsize.width / 10, null);
                        break;
                    case 1:
                        g.drawImage(tileYellowPath, windowsize.width / 10 * j, windowsize.height / 10 * i, windowsize.height / 10, windowsize.width / 10, null);
                        break;

                }
            }
        }
        g.drawImage(sprites[5], Player.playerX, 0 ,100,100,null);
    }
}

【问题讨论】:

  • 你搜索过论坛吗?有很多“为什么我的主要听众不工作”的问题,答案都是一样的。

标签: java swing jpanel keylistener


【解决方案1】:

使用Key Bindings。下面是一个简短的例子来展示如何使用它们:

public class Test
{
    JFrame frame = new JFrame();

    public Test()
    {
        ActionMap actionMap = frame.getRootPane().getActionMap();
        InputMap inputMap = frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

        for (Keys direction : Keys.values())
        {
            actionMap.put(direction.getText(), new KeyBinding(direction.getText()));
            inputMap.put(direction.getKeyStroke(), direction.getText());
        }
        frame.getRootPane().setActionMap(actionMap);
        frame.getRootPane().setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
        frame.setVisible(true);
    }

    private class KeyBinding extends AbstractAction
    {

        private static final long serialVersionUID = 1L;

        public KeyBinding(String text)
        {
            super(text);
            putValue(ACTION_COMMAND_KEY, text);
        }

        @Override
        public void actionPerformed(ActionEvent e)
        {
            String action = e.getActionCommand();
            System.out.println("Key Binding: " + action);
        }
    }

    public static void main(String... args)
    {
        new Test();
    }
}

enum Keys
{
    ESCAPE("Escape", KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)),
    CTRLC("Control-C", KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK)),
    CTRLP("Control-P", KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK)),
    UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)),
    DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)),
    LEFT("Left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)),
    RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));

    private String text;
    private KeyStroke keyStroke;

    Keys(String text, KeyStroke keyStroke)
    {
        this.text = text;
        this.keyStroke = keyStroke;
    }

    public String getText()
    {
        return text;
    }

    public KeyStroke getKeyStroke()
    {
        return keyStroke;
    }

    @Override
    public String toString()
    {
        return text;
    }
}

【讨论】:

  • 感谢您的快速回答,我还不太了解所有代码以及如何将其适应我的项目,但我明天会尽力而为,谢谢!
  • @Boyen 当然可以。如果您不明白,请阅读我在答案中完整链接的教程。如果之后您对 Key Bindings 仍有疑问,请在 SO 上提出另一个问题。
  • 但是话说回来,你有什么解释为什么这不适用于 KeyListener 吗?
  • @Boyen 这可能是错误的,但我认为JPanel 没有键盘焦点,这可能会导致问题。将面板添加到屏幕时使用requestFocus。
  • @syb0rg 避免(焦点)问题并坚持使用键绑定。你是对的,关键监听器只有在它们附加到的组件是可聚焦的并且具有焦点时才会做出反应......
【解决方案2】:

KeyListeners 只会在他们注册的组件是可聚焦的并且有焦点时才会做出反应。大多数 Swing 顶级容器永远不可能直接接收键盘焦点,因为它们有一个 JRootPane,它上面有一个 contentPane(以及其他东西)(防止它永远能够接收键盘焦点),在它上面您添加了另一个组件。

这是KeyListeners 的一个常见问题,也是我们推荐Key Bindings 的主要原因。

另一方面,您的自定义绘画令人担忧。您应该使用 void 覆盖油漆并改为使用 paintComponent。您还应该调用super.paintXxx 以确保Graphics 上下文已为绘画做好适当准备?

详情请见Performing Custom Painting

【讨论】:

    【解决方案3】:

    如果拥有监听器的组件没有焦点,keylistener 不会触发。当我查看您的代码时,似乎您实际上并未将 Player 实例添加到 JFrame,因此它无法获得焦点。

    我建议你将它添加到 JFrame 并使用 this.setVisible(true); 显示框架 这应该可以解决问题

    【讨论】:

    • 对不起,我会用我的面板类更新代码
    猜你喜欢
    • 2021-06-20
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 2017-11-05
    相关资源
    最近更新 更多