当你释放一个移动它的键时,如何让一个矩形停止?

时间:2015-02-10 03:07:07

标签: java swing keylistener

我创建了一个JFrame,其中心有一个矩形,当我按某些键时它会移动。这一切都很好看和花花公子,但是当我释放按键时矩形继续前进。事实上,如果我多次按一次键,矩形会加速。这可能(肯定)是因为我在按住按键时使用定时器来绕过令人讨厌的0.5秒输入延迟。

我认为我必须在keyReleased()方法中添加一些东西,但我不知道该放在那里的东西。有小费吗?感谢。

PS:不要因为我没有使用键绑定而对我大喊大叫。我知道:他们做得更好。但我现在专注于关键听众。

程序:

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

@SuppressWarnings ("serial")
public class GameFrame extends JComponent implements KeyListener
{
    static GameFrame gameFrame = new GameFrame();

    public int x = 350;
    public int y = 250;
    public int keyCode;

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

    @Override
    public void paintComponent (Graphics graphics)
    {
        super.paintComponent (graphics);
        graphics.setColor (Color.BLACK);
        graphics.fillRect (x, y, 100, 100);
    }

    public void keyPressed (KeyEvent event)
    {
        keyCode = event.getKeyCode();

        new Timer (100, new ActionListener()
        {
            public void actionPerformed (ActionEvent event)
            {
                if (keyCode == KeyEvent.VK_LEFT)
                {
                    x--;
                    repaint();
                }
                if (keyCode == KeyEvent.VK_RIGHT)
                {
                    x++;
                    repaint();
                }
                if (keyCode == KeyEvent.VK_UP)
                {
                    y--;
                    repaint();
                }
                if (keyCode == KeyEvent.VK_DOWN)
                {
                    y++;
                    repaint();
                }
            }
        }).start();
    }

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

1 个答案:

答案 0 :(得分:1)

  • 避免KeyListener,严重的是,它们比它们的价值更麻烦,而是使用密钥绑定API。 How to Use Key Bindings

您可以通过多种方式实现这一目标。更好的方法之一是使用间接方法。也就是说,用户按下一个键并举起一个标志来指示按下哪个键,他们释放键,重置标志,表示不再按下该键。

然后使用某种更新循环来根据当前活动的键更改对象的位置。

但是为什么我听到你问这么麻烦呢。当用户按下某个键时,它们是第一次按键和重复按键通知之间的短暂延迟(当按键关闭时,操作系统会向您发送按键事件直到它被释放),这使得动作看起来有点&# 34;交错"

相反,我们引发标志并使用一个常量更新循环来根据标志的状态更改对象的状态,从而平滑键事件,例如......

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
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 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 static class TestPane extends JPanel {

        public enum HorizontalMovement {
            NONE,
            LEFT,
            RIGHT
        }

        private HorizontalMovement horizontalMovement = HorizontalMovement.NONE;

        private int xPos = 0;

        public TestPane() {
            addKeyPressedBinding("left.pressed", KeyEvent.VK_LEFT, new MoveHorizontialAction(HorizontalMovement.LEFT));
            addKeyPressedBinding("right.pressed", KeyEvent.VK_RIGHT, new MoveHorizontialAction(HorizontalMovement.RIGHT));
            addKeyReleasedBinding("left.relesed", KeyEvent.VK_LEFT, new MoveHorizontialAction(HorizontalMovement.NONE));
            addKeyReleasedBinding("right.relesed", KeyEvent.VK_RIGHT, new MoveHorizontialAction(HorizontalMovement.NONE));

            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    switch (horizontalMovement) {
                        case LEFT:
                            xPos--;
                            break;
                        case RIGHT:
                            xPos++;
                            break;
                    }
                    if (xPos < 0) {
                        xPos = 0;
                    } else if (xPos + 50 > getWidth()) {
                        xPos = getWidth() - 50;
                    }
                    repaint();
                }
            });
            timer.start();

        }

        protected void addKeyPressedBinding(String name, int keyCode, Action action) {
            KeyStroke ks = KeyStroke.getKeyStroke(keyCode, 0, false);
            addKeyBinding(name, ks, action);
        }

        protected void addKeyReleasedBinding(String name, int keyCode, Action action) {
            KeyStroke ks = KeyStroke.getKeyStroke(keyCode, 0, true);
            addKeyBinding(name, ks, action);
        }

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

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

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            Rectangle box = new Rectangle(xPos, (getHeight() - 50) / 2, 50, 50);
            g2d.setColor(Color.BLUE);
            g2d.fill(box);
            g2d.dispose();
        }

        protected void addKeyBinding(String left, int VK_LEFT, MoveHorizontialAction moveHorizontialAction) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        protected class MoveHorizontialAction extends AbstractAction {

            private HorizontalMovement movement;

            public MoveHorizontialAction(HorizontalMovement movement) {
                this.movement = movement;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                horizontalMovement = movement;
            }

        }

    }

}