【问题标题】:Java-GUI Key Pressed Not Functioning CorrectlyJava-GUI 键按下不正确
【发布时间】:2017-12-15 03:52:56
【问题描述】:

因此,我查看了有关此问题的大量不同主题,但所有有关如何使其工作的建议;我已经完成了,所以它应该可以工作。我之前已经让它工作了,我做的事情和我在另一个程序中移动图像时一样。无论如何,这是一款类似太空射击游戏的游戏。我正在负责播放器与播放器的课程。您将看到空格键的注释,并且键“e”将在稍后添加一个射击。射击是另一类,这样我可以快速射击并且可以控制每颗子弹,因为有独立的物体。无论如何,我用打印出来的东西做了一些测试,我知道计时器可以工作。我知道 move 方法有效,因为我看到我的图像在屏幕上移动。但是,我无法控制。然后我在按键区域放了一个打印语句,它没有打印任何东西。所以我知道那是某种错误的代码。所以任何帮助都会很棒,因为我很难过。这不适用于大学或高中的课程。这是一个个人项目。代码如下:

import javax.swing.*;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class PlayervsPlayer implements KeyListener,ActionListener{

    private JFrame window;
    private Timer timer;
    private int win_size;
    private int ship_clearence=45;
    private int speed=3;
    private final int stop1=0;
    private final int stop2=1;
    private final int left1=2;
    private final int left2=3;
    private final int right1=4;
    private final int right2=5;
    private int dir1=left1;
    private int dir2=right2;
    Sprite background;
    Sprite ship1=new Sprite("Spaceship.png");
    Sprite ship2=new Sprite("Spaceship2.png");

    public PlayervsPlayer(JFrame w,Sprite backdrop,int win_s) {
        window=w;
        background=backdrop;
        win_size=win_s;
        window.addKeyListener(this);
    }
    public void pvpmain() {
        System.out.println("Player vs Player working!");
        ship1.setSize(125,125);
        ship1.setLocation((int)((win_size/2)-(ship1.getWidth()/2)),win_size-ship1.getHeight()-ship_clearence);
        ship2.setSize(125,125);
        ship2.setLocation((int)((win_size/2)-(ship1.getWidth()/2)),0);
        window.add(ship1,0);
        window.add(ship2,0);
        window.repaint();
        timer = new Timer( 10, this );
        timer.start();
    }
    public void keyPressed(KeyEvent e) {
        int key=e.getKeyCode();
        if ( key == KeyEvent.VK_RIGHT ){
            System.out.println("Right Key");//
            dir1 = right1;
        }
        else if (key==KeyEvent.VK_LEFT) {
            dir1=left1;
        }
        else if (key==KeyEvent.VK_SPACE) {
            //Nothing for now as for shooting
        }
        if (key==KeyEvent.VK_Q) {
            dir2=left2;
        }
        else if (key==KeyEvent.VK_W) {
            dir2=right2;
        }
        else if (key==KeyEvent.VK_E) {
            //Nothing for now as for shooting
        }
    }
    public void move() {
        if (dir1==left1) {
            if (ship1.getX()<=speed) {
                dir1=stop1;
            }
            else {
                ship1.setLocation(ship1.getX()-speed,ship1.getY());
            }
        }
        else if (dir1==right1) {
            if (ship1.getX()+ship1.getWidth()>=win_size-speed) {
                dir1=stop1;
            }
            else {
                ship1.setLocation(ship1.getX()+speed,ship1.getY());
            }
        }
        if (dir2==left2) {
            if (ship2.getX()<=speed) {
                dir2=stop2;
            }
            else {
                ship2.setLocation(ship2.getX()-speed,ship2.getY());
            }
        }
        else if (dir2==right2) {
            if (ship2.getX()+ship2.getWidth()>=win_size-speed) {
                dir2=stop2;
            }
            else {
                ship2.setLocation(ship2.getX()+speed,ship2.getY());
            }
        }
    }
    public void actionPerformed(ActionEvent e) {
        if ( e.getSource() == timer ){
            System.out.println("Timer Working!");
            move();
        }

    }
    public void keyTyped(KeyEvent e) {
        //Nothing

    }
    public void keyReleased(KeyEvent e) {
        //Nothing

    }


}

提前致谢。

【问题讨论】:

    标签: java image user-interface move


    【解决方案1】:

    您的主要问题与KeyListener 在您尝试使用它的应用程序中不可靠有关。 KeyListener 要求它注册的组件能够接收键盘焦点并且在触发按键事件之前具有键盘焦点。焦点很容易被其他组件窃取。

    对您的问题最可靠的解决方案是使用key bindings API,它部分地是为了解决这个问题而开发的。

    您可能还想阅读How to Use Actions 以了解这部分 API 的工作原理

    因此,改编 Trying to move JLabels on a JPanel with GridLayout 中的代码,这是最简单的示例,与您似乎正在尝试做的事情最接近,您最终可能会得到类似...

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.GridLayout;
    import java.awt.Point;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import java.util.ArrayList;
    import java.util.List;
    import javax.swing.AbstractAction;
    import javax.swing.Action;
    import javax.swing.ActionMap;
    import javax.swing.InputMap;
    import javax.swing.JComponent;
    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.CompoundBorder;
    import javax.swing.border.EmptyBorder;
    import javax.swing.border.LineBorder;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            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 class TestPane extends JPanel {
    
            private JLabel player;
    
            public TestPane() {
                player = makeLabel("P");
                player.setSize(player.getPreferredSize());
                add(player);
    
                addKeyBinding("left", KeyEvent.VK_LEFT, new MoveAction(player, -4, 0));
                addKeyBinding("right", KeyEvent.VK_RIGHT, new MoveAction(player, 4, 0));
                addKeyBinding("up", KeyEvent.VK_UP, new MoveAction(player, 0, -4));
                addKeyBinding("down", KeyEvent.VK_DOWN, new MoveAction(player, 0, 4));
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 400);
            }
    
            protected void addKeyBinding(String name, int keyCode, Action action) {
                InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
                ActionMap actionMap = getActionMap();
    
                inputMap.put(KeyStroke.getKeyStroke(keyCode, 0), name);
                actionMap.put(name, action);
            }
    
            protected JLabel makeLabel(String text) {
                JLabel label = new JLabel(text);
                label.setBorder(new CompoundBorder(
                        new LineBorder(Color.GRAY),
                        new EmptyBorder(4, 4, 4, 4)));
                return label;
            }
    
            public class MoveAction extends AbstractAction {
    
                private final int xDelta, yDelta;
                private final JComponent component;
    
                public MoveAction(JComponent component, int xDelta, int yDelta) {
                    this.component = component;
                    this.xDelta = xDelta;
                    this.yDelta = yDelta;
                }
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    Point location = component.getLocation();
                    location.x += xDelta;
                    location.y += yDelta;
                    component.setLocation(location);
                    repaint();
                }
    
            }
    
        }
    
    }
    

    但是多个同时击键呢?

    嗯,这不是一个独特的问题,最常见的解决方法是使用一系列标志来确定当前是否按下了某个键。然后,您可以使用这些标志来确定如何最好地移动对象

    因此,根据第一个示例进行调整,您最终可能会得到类似...

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Point;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import java.util.Set;
    import java.util.TreeSet;
    import javax.swing.AbstractAction;
    import javax.swing.ActionMap;
    import javax.swing.InputMap;
    import javax.swing.JComponent;
    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.CompoundBorder;
    import javax.swing.border.EmptyBorder;
    import javax.swing.border.LineBorder;
    
    public class Test2 {
    
        public static void main(String[] args) {
            new Test2();
        }
    
        public Test2() {
            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 enum Direction {
            UP, DOWN, LEFT, RIGHT;
        }
    
        public class Controller {
            private Set<Direction> directions;
            private JComponent player;
    
            public Controller(JComponent player) {
                this.player = player;
                directions = new TreeSet<>();
            }
    
            public void released(Direction direction) {
                directions.remove(direction);
                updatePosition();
            }
    
            public void pressed(Direction direction) {
                directions.add(direction);
                updatePosition();
            }
    
            protected void updatePosition() {
                Point location = player.getLocation();
                if (directions.contains(Direction.UP)) {
                    location.y -= 4;
                } 
                if (directions.contains(Direction.DOWN)) {
                    location.y += 4;
                }
                if (directions.contains(Direction.LEFT)) {
                    location.x -= 4;
                } 
                if (directions.contains(Direction.RIGHT)) {
                    location.x += 4;
                }
                player.setLocation(location);
            }
    
        }
    
        public class TestPane extends JPanel {
    
            private JLabel player;
    
            public TestPane() {
                player = makeLabel("P");
                player.setSize(player.getPreferredSize());
                add(player);
    
                Controller controller = new Controller(player);
    
                addKeyBinding("left", KeyEvent.VK_LEFT, Direction.LEFT, controller);
                addKeyBinding("right", KeyEvent.VK_RIGHT, Direction.RIGHT, controller);
                addKeyBinding("up", KeyEvent.VK_UP, Direction.UP, controller);
                addKeyBinding("down", KeyEvent.VK_DOWN, Direction.DOWN, controller);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 400);
            }
    
            protected void addKeyBinding(String name, int keyCode, Direction direction, Controller controller) {
                InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
                ActionMap actionMap = getActionMap();
    
                inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, true), name + "-released");
                inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, false), name + "-pressed");
    
                actionMap.put(name + "-released", new MoveAction(direction, controller, true));
                actionMap.put(name + "-pressed", new MoveAction(direction, controller, false));
            }
    
            protected JLabel makeLabel(String text) {
                JLabel label = new JLabel(text);
                label.setBorder(new CompoundBorder(
                        new LineBorder(Color.GRAY),
                        new EmptyBorder(4, 4, 4, 4)));
                return label;
            }
    
            public class MoveAction extends AbstractAction {
    
                private Direction direction;
                private Controller controller;
                private boolean released;
    
                public MoveAction(Direction direction, Controller controller, boolean released) {
                    this.direction = direction;
                    this.controller = controller;
                    this.released = released;
                }
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (released) {
                        controller.released(direction);
                    } else {
                        controller.pressed(direction);
                    }
                }
    
            }
    
        }
    
    }
    

    下一次,尝试使用一些代码而不是强迫它们重组并提出使用这个键绑定的建议。如果你觉得按键绑定这么厉害,不如用按键绑定来修改我的代码,看看它有多复杂

    叹息 - 因为我不应该这样做,即使用你自己的话来说,你也不想要“复制和粘贴”的答案,但是,显然这就是你想要的......

    import javax.swing.JFrame;
    
    import javax.swing.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.beans.PropertyChangeListener;
    
    // I'd prefer to extend from JPanel, as it provides bases for
    // self contained responsibility, but apparently, that's too "advanced"
    public class PlayervsPlayer implements ActionListener {
    
        private JFrame window;
        private Timer timer;
        private int win_size;
        private int ship_clearence = 45;
        private int speed = 3;
        private final int stop1 = 0;
        private final int stop2 = 1;
        private final int left1 = 2;
        private final int left2 = 3;
        private final int right1 = 4;
        private final int right2 = 5;
        private int dir1 = left1;
        private int dir2 = right2;
    //  Sprite background;
        JLabel ship1 = new JLabel("Spaceship.png");
        JLabel ship2 = new JLabel("Spaceship2.png");
    
        public PlayervsPlayer(JFrame w, int win_s) {
            window = w;
    //      background = backdrop;
            win_size = win_s;
    
            JComponent contenPane = (JComponent) w.getContentPane();
    
            InputMap inputMap = contenPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = contenPane.getActionMap();
    
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "player1-left");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "player1-right");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "player2-left");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_E, 0), "player2-right");
    
            // I'd prefer a single "Move Action" class which could
            // make these updates, but that might be "too advanced"
            actionMap.put("player1-left", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Player 1 - left");
                    dir1 = left1;
                }
            });
            actionMap.put("player1-right", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Player 1 - right");
                    dir1 = right1;
                }
            });
            actionMap.put("player2-left", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Player 2 - left");
                    dir2 = left2;
                }
            });
            actionMap.put("player2-right", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Player 2 - right");
                    dir2 = right2;
                }
            });
        }
    
        public void pvpmain() {
            System.out.println("Player vs Player working!");
            ship1.setSize(125, 125);
            ship1.setLocation((int) ((win_size / 2) - (ship1.getWidth() / 2)), win_size - ship1.getHeight() - ship_clearence);
            ship2.setSize(125, 125);
            ship2.setLocation((int) ((win_size / 2) - (ship1.getWidth() / 2)), 0);
            window.add(ship1, 0);
            window.add(ship2, 0);
            window.repaint();
            timer = new Timer(10, this);
            timer.start();
        }
    
        public void move() {
            if (dir1 == left1) {
                if (ship1.getX() <= speed) {
                    dir1 = stop1;
                } else {
                    ship1.setLocation(ship1.getX() - speed, ship1.getY());
                }
            } else if (dir1 == right1) {
                if (ship1.getX() + ship1.getWidth() >= win_size - speed) {
                    dir1 = stop1;
                } else {
                    ship1.setLocation(ship1.getX() + speed, ship1.getY());
                }
            }
            if (dir2 == left2) {
                if (ship2.getX() <= speed) {
                    dir2 = stop2;
                } else {
                    ship2.setLocation(ship2.getX() - speed, ship2.getY());
                }
            } else if (dir2 == right2) {
                if (ship2.getX() + ship2.getWidth() >= win_size - speed) {
                    dir2 = stop2;
                } else {
                    ship2.setLocation(ship2.getX() + speed, ship2.getY());
                }
            }
        }
    
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == timer) {
                System.out.println("Timer Working!");
                move();
            }
        }
    
    }
    

    但是当你释放一个键时玩家不会停止移动......

    嗯,是的,确实如此,但原始代码似乎也没有该功能

    因此,在PlayervsPlayer 构造函数中,我们将现有的绑定替换为类似...

        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "player1-left-pressed");
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "player1-right-pressed");
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "player2-left-pressed");
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_E, 0, false), "player2-right-pressed");
    
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "player1-left-released");
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "player1-right-released");
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), "player2-left-released");
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_E, 0, true), "player2-right-released");
    
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "space");
    
        // I'd prefer this to be a self containted unit of work, but for demonstration purposes
        actionMap.put("player1-left-pressed", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Player 1 - left");
                dir1 = left1;
            }
        });
        actionMap.put("player1-right-pressed", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Player 1 - right");
                dir1 = right1;
            }
        });
        actionMap.put("player2-left-pressed", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Player 2 - left");
                dir2 = left2;
            }
        });
        actionMap.put("player2-right-pressed", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Player 2 - right");
                dir2 = right2;
            }
        });
    
        actionMap.put("player1-left-released", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Player 1 - left");
                dir1 = stop1;
            }
        });
        actionMap.put("player1-right-released", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Player 1 - stop");
                dir1 = stop1;
            }
        });
        actionMap.put("player2-left-released", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Player 2 - stop");
                dir2 = stop2;
            }
        });
        actionMap.put("player2-right-released", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Player 2 - stop");
                dir2 = stop2;
            }
        });
    
        actionMap.put("space", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Pew pew pew");
            }
        });
    

    我还添加了 Space 因为我忘记放在前面的例子中

    我很想看看我的代码的键绑定有多长

    我最喜欢的主题 - 减少和重用。正如我在上面的 cmets 中所说,我希望有一个可以改变某种状态的“移动动作”类,这里我使用了 Set,但你可以传递一个 PlayervsPlayer 的实例和让MoveAction 在其上调用一个方法,告诉类发生了什么操作,我更喜欢这种方法,因为它可以解耦代码(使其更可重用)

    import java.awt.EventQueue;
    import javax.swing.JFrame;
    
    import javax.swing.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.util.Set;
    import java.util.TreeSet;
    
    // I'd prefer to extend from JPanel, as it provides bases for
    // self contained responsibility, but apparently, that's too "advanced"
    public class PlayervsPlayer implements ActionListener {
    
        public static void main(String[] args) {
            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.setSize(400, 400);
                    frame.setLayout(null);
                    new PlayervsPlayer(frame, 400).pvpmain();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        private JFrame window;
        private Timer timer;
        private int win_size;
        private int ship_clearence = 45;
        private int speed = 3;
        private final int stop1 = 0;
        private final int stop2 = 1;
        private final int left1 = 2;
        private final int left2 = 3;
        private final int right1 = 4;
        private final int right2 = 5;
    //  private int dir1 = left1;
    //  private int dir2 = right2;
    //  Sprite background;
        JLabel ship1 = new JLabel("Spaceship.png");
        JLabel ship2 = new JLabel("Spaceship2.png");
    
        private Set<Integer> playerKeys;
    
        public PlayervsPlayer(JFrame w, int win_s) {
            window = w;
    //      background = backdrop;
            win_size = win_s;
    
            playerKeys = new TreeSet<>();
            playerKeys = new TreeSet<>();
    
            playerKeys.add(left1);
            playerKeys.add(right2);
    
            JComponent contenPane = (JComponent) w.getContentPane();
    
            InputMap inputMap = contenPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = contenPane.getActionMap();
    
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "player1-left");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "player1-right");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "player2-left");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_E, 0), "player2-right");
    
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "player1-left-pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "player1-right-pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "player2-left-pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_E, 0, false), "player2-right-pressed");
    
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "player1-left-released");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "player1-right-released");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), "player2-left-released");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_E, 0, true), "player2-right-released");
    
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "space");
    
            // I'd prefer this to be a self containted unit of work, but for demonstration purposes
            actionMap.put("player1-left-pressed", new MoveAction(playerKeys, left1, false));
            actionMap.put("player1-right-pressed", new MoveAction(playerKeys, right1, false));
    
            actionMap.put("player2-left-pressed", new MoveAction(playerKeys, left2, false));
            actionMap.put("player2-right-pressed", new MoveAction(playerKeys, right2, false));
    
            actionMap.put("player1-left-released", new MoveAction(playerKeys, left1, true));
            actionMap.put("player1-right-released", new MoveAction(playerKeys, right1, true));
    
            actionMap.put("player2-left-released", new MoveAction(playerKeys, left2, true));
            actionMap.put("player2-right-released", new MoveAction(playerKeys, right2, true));
    
            actionMap.put("space", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Pew pew pew");
                }
            });
        }
    
        public void pvpmain() {
            System.out.println("Player vs Player working!");
            ship1.setSize(125, 125);
            ship1.setLocation((int) ((win_size / 2) - (ship1.getWidth() / 2)), win_size - ship1.getHeight() - ship_clearence);
            ship2.setSize(125, 125);
            ship2.setLocation((int) ((win_size / 2) - (ship1.getWidth() / 2)), 0);
            window.add(ship1, 0);
            window.add(ship2, 0);
            window.repaint();
            timer = new Timer(10, this);
            timer.start();
        }
    
        public void move() {
            if (playerKeys.contains(left1)) {
                if (ship1.getX() <= speed) {
                    playerKeys.clear();
                } else {
                    ship1.setLocation(ship1.getX() - speed, ship1.getY());
                }
            } else if (playerKeys.contains(right1)) {
                if (ship1.getX() + ship1.getWidth() >= win_size - speed) {
                    playerKeys.clear();
                } else {
                    ship1.setLocation(ship1.getX() + speed, ship1.getY());
                }
            }
            if (playerKeys.contains(left2)) {
                if (ship2.getX() <= speed) {
                    playerKeys.clear();
                } else {
                    ship2.setLocation(ship2.getX() - speed, ship2.getY());
                }
            } else if (playerKeys.contains(right2)) {
                if (ship2.getX() + ship2.getWidth() >= win_size - speed) {
                    playerKeys.clear();
                } else {
                    ship2.setLocation(ship2.getX() + speed, ship2.getY());
                }
            }
        }
    
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == timer) {
                move();
            }
        }
    
        public class MoveAction extends AbstractAction {
    
            private Set<Integer> keys;
            private Integer action;
            private boolean released;
    
            public MoveAction(Set<Integer> keys, Integer action, boolean released) {
                this.keys = keys;
                this.action = action;
                this.released = released;
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                if (released) {
                    keys.remove(action);
                } else {
                    keys.add(action);
                }
            }
    
        }
    
    }
    

    【讨论】:

    • 因此,既然您如此受驱动以至于网格是一个很好的例子,那么让我向您展示它的问题。 1. 它并没有说明我只需要键绑定需要哪些导入。所以我不知道哪些进口是相关的。 2.它有另一个扩展类,那么为了使键绑定起作用,那是必需的吗?就像我必须为键绑定扩展一个类? 3. addkeybindings 通常像方法区域的主要方法类型一样进入,还是特定于这个例子? 4. 行动是什么意思?那是我放精灵的地方吗? 5.如果我必须扩展,执行的动作是否必须进入扩展
    • @BobG。 “1. 它并没有说明我需要哪些导入仅用于键绑定” - 确实如此,但是,您必须阅读其他相关示例(如键绑定教程中的示例)和 JavaDocs完全了解哪些进口最相关 - 没有答案会给你一个绝对答案只是那个问题
    • @BobG。 “2. 它有另一个扩展的类,那么为了使键绑定起作用,那是必需的吗?” - 键绑定仅适用于基于 JComponent 的类。由于直接从JFrame 扩展或使用有问题和限制,我个人喜欢从JPanel 作为我的基类开始,它解决了很多其他问题
    • @BobG。 “3. addkeybindings 通常像方法区域的主要方法类型一样进入,还是特定于此示例?” - 不,示例清楚地显示了它们可以在哪里建立,作为一般规则,它们应该由负责管理它们的类设置,在示例的情况下,这往往是我用作基础类的JPanel
    • @BobG。现在您有了三个示例,以及指向教程的链接,现在由您来获取所提供的信息并根据您的需要进行调整。此处的目的是提供一个学习基础,您可以从中成长并更好地理解 API 的工作原理以及如何使用。打破例子,移动东西,看看它做了什么
    猜你喜欢
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多