gpt4 book ai didi

java - 当您释放移动矩形的键时,如何让矩形停止?

转载 作者:行者123 更新时间:2023-12-01 11:56:19 25 4
gpt4 key购买 nike

我创建了一个 JFrame,其中心有一个矩形,当我按下某些键时,该矩形会移动。这一切都很漂亮,但当我松开按键时,矩形会继续移动。事实上,如果我多次按下某个键,矩形就会加速。这可能(肯定)是因为我使用计时器来解决按住按键时令人讨厌的 0.5 秒输入延迟。

我想我必须在 keyReleased() 方法中添加一些内容,但我不知道该放什么。有小费吗?谢谢。

PS:不要因为我不使用按键绑定(bind)而对我大喊大叫。我知道:他们更好。但我目前关注的是主要听众。

程序:

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) {}
}

最佳答案

  • 避免使用 KeyListener,说实话,它们带来的麻烦比其值(value)更大,请改用键绑定(bind) API。 How to Use Key Bindings

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

然后,您可以使用某种更新循环来根据当前处于 Activity 状态的键来更改对象的位置。

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

相反,我们提出标志并使用恒定的更新循环来根据标志的状态更改对象的状态,这可以平滑关键事件,例如......

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

}

}

}

关于java - 当您释放移动矩形的键时,如何让矩形停止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28423393/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com