(사용자 정의 키를 생각)하지만, 약간의 테스트 후 나는 그들이 여전히 같은 말을 더듬을 남겼 것을 의미한다 문제.
OS의 반복 속도에 의존하지 마십시오. 모든 플랫폼마다 다를 수 있으며 사용자가 사용자 정의 할 수도 있습니다.
대신 타이머를 사용하여 일정을 예약하십시오. keyPressed에서 Timer를 시작하고 keyReleased에서 Timer를 중지합니다. 이벤트의 순서의 keyPressed,의 keyPressed,의 keyPressed ...의 keyReleased입니다
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.Map;
import java.util.HashMap;
import javax.imageio.ImageIO;
import javax.swing.*;
public class KeyboardAnimation implements ActionListener
{
private final static String PRESSED = "pressed ";
private final static String RELEASED = "released ";
private final static Point RELEASED_POINT = new Point(0, 0);
private JComponent component;
private Timer timer;
private Map<String, Point> pressedKeys = new HashMap<String, Point>();
public KeyboardAnimation(JComponent component, int delay)
{
this.component = component;
timer = new Timer(delay, this);
timer.setInitialDelay(0);
}
public void addAction(String keyStroke, int deltaX, int deltaY)
{
// InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
InputMap inputMap = component.getInputMap();
ActionMap actionMap = component.getActionMap();
String pressedKey = PRESSED + keyStroke;
KeyStroke pressedKeyStroke = KeyStroke.getKeyStroke(pressedKey);
Action pressedAction = new AnimationAction(keyStroke, new Point(deltaX, deltaY));
inputMap.put(pressedKeyStroke, pressedKey);
actionMap.put(pressedKey, pressedAction);
String releasedKey = RELEASED + keyStroke;
KeyStroke releasedKeyStroke = KeyStroke.getKeyStroke(releasedKey);
Action releasedAction = new AnimationAction(keyStroke, RELEASED_POINT);
inputMap.put(releasedKeyStroke, releasedKey);
actionMap.put(releasedKey, releasedAction);
}
private void handleKeyEvent(String keyStroke, Point moveDelta)
{
// Keep track of which keys are pressed
if (RELEASED_POINT == moveDelta)
pressedKeys.remove(keyStroke);
else
pressedKeys.put(keyStroke, moveDelta);
// Start the Timer when the first key is pressed
if (pressedKeys.size() == 1)
{
timer.start();
}
// Stop the Timer when all keys have been released
if (pressedKeys.size() == 0)
{
timer.stop();
}
}
// Invoked when the Timer fires
public void actionPerformed(ActionEvent e)
{
moveComponent();
}
// Move the component to its new location
private void moveComponent()
{
int componentWidth = component.getSize().width;
int componentHeight = component.getSize().height;
Dimension parentSize = component.getParent().getSize();
int parentWidth = parentSize.width;
int parentHeight = parentSize.height;
// Calculate new move
int deltaX = 0;
int deltaY = 0;
for (Point delta : pressedKeys.values())
{
deltaX += delta.x;
deltaY += delta.y;
}
// Determine next X position
int nextX = Math.max(component.getLocation().x + deltaX, 0);
if (nextX + componentWidth > parentWidth)
{
nextX = parentWidth - componentWidth;
}
// Determine next Y position
int nextY = Math.max(component.getLocation().y + deltaY, 0);
if (nextY + componentHeight > parentHeight)
{
nextY = parentHeight - componentHeight;
}
// Move the component
component.setLocation(nextX, nextY);
}
private class AnimationAction extends AbstractAction implements ActionListener
{
private Point moveDelta;
public AnimationAction(String keyStroke, Point moveDelta)
{
super(PRESSED + keyStroke);
putValue(ACTION_COMMAND_KEY, keyStroke);
this.moveDelta = moveDelta;
}
public void actionPerformed(ActionEvent e)
{
handleKeyEvent((String)getValue(ACTION_COMMAND_KEY), moveDelta);
}
}
public static void main(String[] args)
{
JPanel contentPane = new JPanel();
contentPane.setLayout(null);
Icon dukeIcon = null;
try
{
dukeIcon = new ImageIcon("dukewavered.gif");
// dukeIcon = new ImageIcon(ImageIO.read(new URL("http://duke.kenai.com/iconSized/duke4.gif")));
}
catch(Exception e)
{
System.out.println(e);
}
JLabel duke = new JLabel(dukeIcon);
duke.setSize(duke.getPreferredSize());
duke.setLocation(100, 100);
contentPane.add(duke);
KeyboardAnimation navigation = new KeyboardAnimation(duke, 24);
navigation.addAction("LEFT", -3, 0);
navigation.addAction("RIGHT", 3, 0);
navigation.addAction("UP", 0, -3);
navigation.addAction("DOWN", 0, 3);
navigation.addAction("A", -5, 0);
navigation.addAction("S", 5, 0);
navigation.addAction("Z", 0, -5);
navigation.addAction("X", 0, 5);
navigation.addAction("V", 5, 5);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame.getContentPane().add(new JTextField(), BorderLayout.SOUTH);
frame.getContentPane().add(contentPane);
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
이 코드
Windows에서 테스트되었습니다.
그러나 Mac (또는 Unix)에서 이벤트 순서가 keyPressed, keyReleased, keyPressed, keyReleased ...라고 생각합니다. 따라서이 코드가 현재 코드보다 더 잘 작동하는지 확신 할 수 없습니다.
원래 나는 Key Bindings에 대한 답변을 가지고 있었지만 약간의 테스트를 거친 후에도 똑같은 문제가 계속 발생했다. +1하지만 다른 것들. – syb0rg
@ syb0rg 그 이유는 그 작은 깃발이 필요합니다;). 마지막 예제는 키 이벤트가 가속 델타를 적용하도록 허용하는 것에 대한 깔끔한 아이디어를 보여줍니다. 누를 때마다 델타가 증가하고 델타가 반전되고 시간이 지남에 따라 오브젝트가 느려질 때까지 증가합니다.) – MadProgrammer
@ syb0rg 원칙을 설명하기위한 간단한 예제를 추가했습니다.) – MadProgrammer