-1

我目前正在研究一个项目,当我尝试添加自己的类中的自己的键侦听器时,它不起作用,当您按下键时没有任何反应,而且我已经有一段时间了。我不能使用键绑定,所以请不要让我更改为那些,因为它们不支持我正在做的事情,因为它们不支持一次多次按键(相信我,我试过了)。它专注于使用panel.setFocusable(true);and panel.requestFocusInWindow();,我什至用frame.setFocusable(true);and对框架做了它,frame.requestFocusInWindow();但仍然没有。这些都是我的文件:

编辑:我添加了一个SwingUtilities.invokeLater(new Runnable() {,但仍然没有,我目前正在做 MadProgrammer 所说的关于 KeyBindings 的内容,但截至目前,我遇到了一些我正在尝试修复的奇怪错误。

Game.Java:

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.JPanel;
import com.PK.character.MainCharacter;

public class Game extends JPanel{
    private static final long serialVersionUID = -2398443377427441196L;
    public static Image gamemainmenu = Toolkit.getDefaultToolkit().createImage("src/resources/homerscared.jpg");
    public static boolean menu;
    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(gamemainmenu, 10, 10, null);
        menu = true;
        if (menu = true){
            g.drawImage(MainCharacter.MainCharacterImage, 100, 100, null);
        }
    }
}

ButtonListener.Java:

import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JPanel;

import com.PK.PK;
import com.PK.character.MainCharacter;

public class ButtonListener implements KeyListener{
private static JPanel gamepanel = PK.panel;
@Override
public void keyPressed(KeyEvent arg0) {
    /**N=0
     * NE=1
     * E=2
     * SE=3
     * S=4
     * SW=5
     * W=6
     * NW=7
     */
    if (arg0.getKeyChar() == KeyEvent.VK_DOWN){
        MainCharacter.move(4, MainCharacter.CharacterS);
        System.out.println("down pressed");
        gamepanel.setForeground(Color.BLUE);
    }
    if (arg0.getKeyChar() == KeyEvent.VK_UP){
        MainCharacter.move(0, MainCharacter.CharacterN);
        System.out.println("up pressed");
    }
    if (arg0.getKeyChar() == KeyEvent.VK_LEFT){
        MainCharacter.move(6, MainCharacter.CharacterW);
        System.out.println("left pressed");
    }
    if (arg0.getKeyChar() == KeyEvent.VK_RIGHT){
        MainCharacter.move(2, MainCharacter.CharacterE);
        System.out.println("right pressed");

    }
    if (arg0.getKeyChar() == KeyEvent.VK_RIGHT && arg0.getKeyChar() == KeyEvent.VK_UP){
        MainCharacter.move(1, MainCharacter.CharacterNE);
        System.out.println("right and up pressed");
    }
    if (arg0.getKeyChar() == KeyEvent.VK_RIGHT && arg0.getKeyChar() == KeyEvent.VK_DOWN){
        MainCharacter.move(3, MainCharacter.CharacterSE);
        System.out.println("up and right pressed");
    }
    if (arg0.getKeyChar() == KeyEvent.VK_LEFT && arg0.getKeyChar() == KeyEvent.VK_UP){
        MainCharacter.move(7, MainCharacter.CharacterNW);
        System.out.println("up and left pressed");
    }
    if (arg0.getKeyChar() == KeyEvent.VK_LEFT && arg0.getKeyChar() == KeyEvent.VK_DOWN){
        MainCharacter.move(5, MainCharacter.CharacterSW);
        System.out.println("left and down pressed");
    }
}

@Override
public void keyReleased(KeyEvent arg0) {

}

@Override
public void keyTyped(KeyEvent arg0) {

}

}

PK.Java (Main Class):

package com.PK;

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import com.PK.movement.ButtonListener;

public class PK {
    public static short CharacterX, CharacterY;
    public static final int width = 800;
    public static final int height = 600;
    public static Date date = new Date();
    public static String dString = date.toString();
    public static String dFormat = "[" + dString + "]: ";
    public static JFrame frame = new JFrame();
    public static JPanel panel = new Game();
    public static KeyListener bt = new ButtonListener();
    public static Image logobasic = Toolkit.getDefaultToolkit().createImage("src/resources/logo-basic.png");
public static void main(String[] args){
    frame.setContentPane(panel);
    System.out.println(dFormat + "Panel added to frame");
    frame.setSize(width, height);
    frame.setTitle("PK");
    frame.setIconImage(logobasic);
    frame.setVisible(true);
    frame.setJMenuBar(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    System.out.println(dFormat + "Frame settings set");
    System.out.println(dFormat + "Launching...");   
}

public PokemonUniverse(){
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            panel.setFocusable(true);
            panel.requestFocusInWindow();
            System.out.println(dFormat + "Panel focused");
            panel.addKeyListener(bt);
            System.out.println(dFormat + "KeyListener added to panel");
            frame.setFocusable(true);
            frame.requestFocusInWindow();
            System.out.println(dFormat + "Frame focused");
            frame.addKeyListener(bt);
            System.out.println(dFormat + "KeyListener added to frame");
        }
    });
}

MainCharacter.Java

package com.PK;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

import javax.swing.JPanel;

import com.PK.Game;
import com.PK.PK;

@SuppressWarnings("unused")
public class MainCharacter {
static Toolkit tk = Toolkit.getDefaultToolkit();
public static Image MainCharacterImage = PK.logobasic, CharacterS, CharacterN, CharacterW, CharacterE, CharacterSE, CharacterNE, CharacterSW, CharacterNW;
private static JPanel gamepanel = PK.panel;
private static short Y = PK.CharacterY;
private static short X = PK.CharacterX;

/**N=0
 * NE=1
 * E=2
 * SE=3
 * S=4
 * SW=5
 * W=6
 * NW=7
 */
public static void move(int direction, Image FacingDirection) {
    if (direction == 0){
        Y++;
        MainCharacterImage = FacingDirection;
        gamepanel.repaint();
    }
    else if (direction == 1){
        Y++;
        X++;
        MainCharacterImage = FacingDirection;
        gamepanel.repaint();
    }
    else if (direction == 2){
        X++;
        MainCharacterImage = FacingDirection;
        gamepanel.repaint();
    }
    else if (direction == 3){
        Y--;
        X++;
        MainCharacterImage = FacingDirection;
        gamepanel.repaint();
    }
    else if (direction == 4){
        Y--;
        MainCharacterImage = FacingDirection;
        gamepanel.repaint();
    }
    else if (direction == 5){
        Y--;
        X--;
        MainCharacterImage = FacingDirection;
        gamepanel.repaint();

    }
    else if (direction == 6){
        X--;
        MainCharacterImage = FacingDirection;
        gamepanel.repaint();
    }
    else if (direction == 7){
        X--;
        Y++;
        MainCharacterImage = FacingDirection;
        gamepanel.repaint();
    }
    else{
        MainCharacterImage = PK.logobasic;
        gamepanel.repaint();
    }
}
}
4

1 回答 1

2

简短的回答是,不要使用KeyListener,使用 Key Bindings API,它可以让您克服这些缺点并配置触发它们所需的焦点级别。

有关更多详细信息,请参阅如何使用键绑定

更新

首先,你需要停止以这样的绝对术语思考,而开始以更抽象的概念思考。你的游戏不应该关心事情是如何完成的,只有当事情发生时。

问题不在于键绑定 API,而在于您如何看待问题。

例如,您不应该关心“up”事件是如何触发的,只关心它是如何触发的。这意味着触发器可能来自操纵杆、游戏控制器、网络服务器、通过力甚至键盘的精神控制。然后游戏将相应地对这种状态变化做出反应。

键绑定

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class KeyBindingsTest {

    public static void main(String[] args) {
        new KeyBindingsTest();
    }

    public KeyBindingsTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public interface InputManager {

        public void upWasPerformed(boolean active);
        public void downWasPerformed(boolean active);
        public void leftWasPerformed(boolean active);
        public void rightWasPerformed(boolean active);

    }

    public static class TestPane extends JPanel implements InputManager {

        public static final LineBorder LINE_BORDER = new LineBorder(Color.RED);
        public static final EmptyBorder EMPTY_BORDER = new EmptyBorder(1, 1, 1, 1);

        private JLabel up;
        private JLabel down;
        private JLabel left;
        private JLabel right;

        public TestPane() {
            setLayout(new GridBagLayout());
            up = new JLabel("UP");
            up.setBorder(EMPTY_BORDER);

            down = new JLabel("DOWN");
            down.setBorder(EMPTY_BORDER);

            left = new JLabel("LEFT");
            left.setBorder(EMPTY_BORDER);

            right = new JLabel("RIGHT");
            right.setBorder(EMPTY_BORDER);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            add(left, gbc);
            gbc.gridx++;
            gbc.gridy = 0;
            add(up, gbc);
            gbc.gridy = 2;
            add(down, gbc);
            gbc.gridx++;
            gbc.gridy = 1;
            add(right, gbc);

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "up.pressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "up.released");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "down.pressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "down.released");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "left.pressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "left.released");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "right.pressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "right.released");

            ActionMap am = getActionMap();
            am.put("up.pressed", new UpAction(this, true));
            am.put("up.released", new UpAction(this, false));
            am.put("down.pressed", new DownAction(this, true));
            am.put("down.released", new DownAction(this, false));
            am.put("left.pressed", new LeftAction(this, true));
            am.put("left.released", new LeftAction(this, false));
            am.put("right.pressed", new RightAction(this, true));
            am.put("right.released", new RightAction(this, false));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        public void upWasPerformed(boolean active) {
            up.setBorder(active ? LINE_BORDER : EMPTY_BORDER);
        }

        @Override
        public void downWasPerformed(boolean active) {
            down.setBorder(active ? LINE_BORDER : EMPTY_BORDER);
        }

        @Override
        public void leftWasPerformed(boolean active) {
            left.setBorder(active ? LINE_BORDER : EMPTY_BORDER);
        }

        @Override
        public void rightWasPerformed(boolean active) {
            right.setBorder(active ? LINE_BORDER : EMPTY_BORDER);
        }

    }

    public static abstract class InputManagerAction extends AbstractAction {

        private InputManager manager;
        private boolean activate;

        public InputManagerAction(InputManager manager, boolean activate) {
            this.manager = manager;
            this.activate = activate;
        }

        public InputManager getManager() {
            return manager;
        }

        public boolean shouldActivate() {
            return activate;
        }

    }

    public static class UpAction extends InputManagerAction {

        public UpAction(InputManager manager, boolean activate) {
            super(manager, activate);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getManager().upWasPerformed(shouldActivate());
        }

    }

    public static class DownAction extends InputManagerAction {

        public DownAction(InputManager manager, boolean activate) {
            super(manager, activate);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getManager().downWasPerformed(shouldActivate());
        }

    }

    public static class LeftAction extends InputManagerAction {

        public LeftAction(InputManager manager, boolean activate) {
            super(manager, activate);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getManager().leftWasPerformed(shouldActivate());
        }

    }

    public static class RightAction extends InputManagerAction {

        public RightAction(InputManager manager, boolean activate) {
            super(manager, activate);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getManager().rightWasPerformed(shouldActivate());
        }

    }
}

现在,您有两个选择,您可以改变您的思维方式并利用 API 来解决您的问题并使您的程序更加灵活和可配置(因为用户可能希望更改触发事件的键) 或者您可以继续尝试使用无法满足您的需求并且整个社区会鼓励您不要继续使用的 API...

于 2014-10-05T23:11:55.727 回答