如何使用 KeyListener 在 JFrame 中移动一个矩形?

How to move move a rectangle in JFrame using KeyListener?

我试图让我的 JFrame 中的一个矩形在我按下键盘上的给定键时移动,但我似乎很难做到这一点。这是我的代码:

package TestPackage;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JComponent;

public class Mainframe extends JComponent implements KeyListener
{
    private static final long serialVersionUID = 1L;

    int x = 350;
    int y = 250;

    public static void main (String[] args)
    {
        JFrame frame = new JFrame ("Mainframe");
        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        frame.setSize (800, 600);
        frame.setFocusable (true);
        frame.getContentPane().setBackground (Color.WHITE);
        frame.getContentPane().add (new Mainframe());
        frame.addKeyListener (new Mainframe());
        frame.setVisible (true);
    }

    public void paint (Graphics graphics)
    {
        graphics.setColor (Color.BLACK);
        graphics.fillRect (x, y, 100, 100);
    }

    public void keyPressed (KeyEvent event)
    {
        if (event.getKeyCode() == KeyEvent.VK_A)
        {
            x++;
            repaint();
        }
        else if (event.getKeyCode() == KeyEvent.VK_D)
        {
            y++;
            repaint();
        }
    }

    public void keyReleased (KeyEvent event) {}
    public void keyTyped (KeyEvent event) {}
}

我确定这是我的 KeyListener 的问题,因为其他一切正常。有人知道我做错了什么吗?谢谢

像这样制作你的 main 就可以了

 public static void main (String[] args)
    {
        JFrame frame = new JFrame ("Mainframe");
        JComponent test = new Mainframe();
        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        frame.setSize (800, 600);
        frame.setFocusable (true);
        frame.getContentPane().setBackground (Color.WHITE);
        frame.getContentPane().add (test);
        frame.addKeyListener ((KeyListener) test);
        frame.setVisible (true);
    }
  1. 您正在创建 MainFrame 的两个实例,一个添加到框架中,另一个用作 JFrameKeyListener,这意味着对 KeyListener 实例生成 x/y 值,不会被 UI
  2. 上的实例看到
  3. 不要使用 KeyListener,它有太多与焦点相关的问题,请使用专为克服这些问题而设计的键绑定 API。参见 How to Use Key Bindings
  4. 不要覆盖 paint(特别是如果您不打算调用 super.paint),相反,您应该覆盖 paintComponent 方法(并调用 super.paintComponent).有关详细信息,请参阅 Painting in AWT and Swing and Performing Custom Painting
  5. 确保您仅在事件调度线程的上下文中创建和修改 UI,有关详细信息,请参阅 Initial Threads

例如...

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
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.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Mainframe extends JComponent {

    private static final long serialVersionUID = 1L;

    int x = 350;
    int y = 250;

    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("Mainframe");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setSize(800, 600);
                frame.setFocusable(true);
                frame.getContentPane().setBackground(Color.WHITE);
                frame.getContentPane().add(new Mainframe());
                frame.setVisible(true);
            }
        });
    }

    public Mainframe() {
        bindKeyWith("y.up", KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), new VerticalAction(-1));
        bindKeyWith("y.down", KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), new VerticalAction(1));
        bindKeyWith("x.left", KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), new HorizontalAction(-1));
        bindKeyWith("x.right", KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), new HorizontalAction(1));
    }

    protected void bindKeyWith(String name, KeyStroke keyStroke, Action action) {
        InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
        ActionMap am = getActionMap();

        im.put(keyStroke, name);
        am.put(name, action);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
        g.setColor(Color.BLACK);
        g.fillRect(x, y, 100, 100);
    }

    public abstract class MoveAction extends AbstractAction {

        private int delta;

        public MoveAction(int delta) {
            this.delta = delta;
        }

        public int getDelta() {
            return delta;
        }

        protected abstract void applyDelta();

        @Override
        public void actionPerformed(ActionEvent e) {
            applyDelta();
        }

    }

    public class VerticalAction extends MoveAction {

        public VerticalAction(int delta) {
            super(delta);
        }

        @Override
        protected void applyDelta() {
            int delta = getDelta();
            y += delta;
            if (y < 0) {
                y = 0;
            } else if (y + 100 > getHeight()) {
                y = getHeight() - 100;
            }
            repaint();
        }

    }
    public class HorizontalAction extends MoveAction {

        public HorizontalAction(int delta) {
            super(delta);
        }

        @Override
        protected void applyDelta() {
            int delta = getDelta();
            x += delta;
            if (x < 0) {
                x = 0;
            } else if (x + 100 > getWidth()) {
                x = getWidth() - 100;
            }
            repaint();
        }

    }
}