Java 对象移动

2022-01-13 00:00:00 keyboard java path-finding

我试图让一个圆圈在键盘输入中移动.我根本无法移动对象.有人可以帮我找出问题所在吗?这是我的代码:

I am trying to get a circle to move through the input of a keyboard. I am not able to move the object at all. Can someone help me figure out what is wrong? Here is my code:

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

import javax.swing.JPanel;


public class AlienInvader extends JPanel implements KeyListener{

    Constants constant = new Constants();

    public void update() {
        constant.x += constant.xvel;
        addKeyListener(this);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.MAGENTA);
        g.fillOval(constant.x, constant.y, 30, 30);
        repaint();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println(constant.x);
        switch(e.getKeyCode()) {
        case KeyEvent.VK_LEFT:
            constant.xvel = -1;
            break;
        case KeyEvent.VK_RIGHT:
            constant.xvel = 1;
            break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        switch(e.getKeyCode()) {
        case KeyEvent.VK_LEFT:
            constant.xvel = -1;
            break;
        case KeyEvent.VK_RIGHT:
            constant.xvel = 1;
            break;
        }
    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }


}

我不确定我做错了什么.我以为是因为我没有调用update方法,但是当我在paintComponent中添加了一个if语句(所以它只调用自己一次)并尝试了它时,我没有运气.

I am not sure what I am doing wrong. I thought it was because I wasn't calling the update method, but when I added a if statement in paintComponent (so it only calls itself once) and tried it, I had no luck.

推荐答案

首先,不要在任何 paintXxx 方法中调用 repaint.绘制方法通常被调用以响应对 repaint 的调用,因此您正在创建一个令人讨厌的、永无止境的、消耗资源的地狱循环.

To start with, don't call repaint within any paintXxx method. Paint methods are typically called in response to a call to repaint, therefore you are creating a nasty, never ending, ever consuming loop of resource hell.

其次,KeyListeners 仅在 1- 注册的组件可聚焦 2- 注册的组件具有焦点时才响应键事件.

Secondly, KeyListeners only respond to key events when 1- The component the are registered to are focusable 2- When the component they are registered to have focus.

在这种情况下,它们是一个糟糕的选择.改用 键绑定

They are a poor choice in this case. Use Key bindings instead

第三,您没有提供 preferredSize 提示供布局管理器使用.在您的情况下,这可能是也可能不是一件坏事,但您的组件可能会以 0x0 的大小布局

Thirdly, you are not providing a preferredSize hint for layout managers to use. This may or may not be a bad thing in your case, but it's possible that you component will be laid out with a size of 0x0

示例

类似......

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MoveCircle {

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

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

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

    public class TestPane extends JPanel {

        private int xDelta = 0;
        private int keyPressCount = 0;
        private Timer repaintTimer;
        private int xPos = 0;
        private int radius = 10;

        public TestPane() {
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "pressed.left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "pressed.right");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "released.left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "released.right");

            am.put("pressed.left", new MoveAction(-2, true));
            am.put("pressed.right", new MoveAction(2, true));
            am.put("released.left", new MoveAction(0, false));
            am.put("released.right", new MoveAction(0, false));

            repaintTimer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    xPos += xDelta;
                    if (xPos < 0) {
                        xPos = 0;
                    } else if (xPos + radius > getWidth()) {
                        xPos = getWidth() - radius;
                    }
                    repaint();
                }
            });
            repaintTimer.setInitialDelay(0);
            repaintTimer.setRepeats(true);
            repaintTimer.setCoalesce(true);

        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            g2d.drawOval(xPos, 0, radius, radius);
            g2d.dispose();
        }

        public class MoveAction extends AbstractAction {

            private int direction;
            private boolean keyDown;

            public MoveAction(int direction, boolean down) {
                this.direction = direction;
                keyDown = down;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                xDelta = direction;
                if (keyDown) {
                    if (!repaintTimer.isRunning()) {
                        repaintTimer.start();
                    }
                } else {
                    repaintTimer.stop();
                }
            }
        }
    }
}

例如...

相关文章