1

我已经尝试解决这个问题大约 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);
    }
}
4

3 回答 3

4

使用键绑定。这是一个简短的示例来展示如何使用它们:

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;
    }
}
于 2013-05-05T20:42:49.837 回答
1

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

这是一个常见的已知问题,也是我们推荐使用Key BindingsKeyListeners的主要原因。

另一方面,您的定制绘画令人担忧。您应该使用 void 覆盖油漆并改为使用paintComponent. 您还应该打电话super.paintXxx以确保Graphics为绘画做好了适当的准备?

有关更多详细信息,请参阅执行自定义绘画

于 2013-05-05T21:12:04.953 回答
0

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

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

于 2013-05-05T20:45:49.947 回答