如何使用KeyListener在JFrame中移动矩形? [英] How to move move a rectangle in JFrame using KeyListener?

查看:102
本文介绍了如何使用KeyListener在JFrame中移动矩形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我按键盘上的给定键时,我试图在JFrame中移动一个矩形,但是这样做似乎很困难.这是我的代码:

I'm trying to get a rectangle in my JFrame to move when I press a given key on the keyboard, but I'm seemingly having a hard time doing that. Here's my code:

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的问题,因为其他所有功能都可以正常工作.有人知道我在做什么错吗?谢谢.

I'm sure it's a problem with my KeyListener, as everything else works perfectly. Does anybody know what I'm doing wrong? Thanks.

推荐答案

  1. 您要创建两个MainFrame实例,一个添加到框架中,另一个用作JFrameKeyListener,这意味着KeyListener实例对值,UI上的实例将不会看到该值
  2. 不要使用KeyListener,它有太多与焦点相关的问题,请使用旨在解决这些问题的Key Bindings API.请参见如何使用键绑定
  3. 不要覆盖paint(尤其是如果您不打算调用super.paint),而是应该覆盖paintComponent方法(并调用super.paintComponent).请参见 AWT和Swing中的绘画
  1. You're creating two instances of MainFrame, one you add to the frame and one you use as the JFrame's KeyListener, this means that any modifications the KeyListener instance makes to the x/y values, won't be seen by the instance on the UI
  2. Don't use KeyListener, it has too many focus related issues, use the Key Bindings API which was designed to overcome these issues. See How to Use Key Bindings
  3. Don't override paint (and especially if you're not going to call super.paint), instead, you should override the paintComponent method (and call super.paintComponent). See Painting in AWT and Swing and Performing Custom Painting for more details
  4. Make sure you are creating and modifying the UI only from within the context of the Event Dispatching Thread, see Initial Threads for more details

例如...

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();
        }

    }
}

这篇关于如何使用KeyListener在JFrame中移动矩形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆