[英]how to move an object in a JPanel using the arrow keys
I am trying to create a small program with Windowbuilder that simply paints a red rectangle (called car1) in a JPanel and move it around by pressing the arrow keys; 我正在尝试使用Windowbuilder创建一个小程序,该程序简单地在JPanel中绘制一个红色矩形(称为car1),然后通过按箭头键将其移动。 to do that I associated to the arrows a method to change the x position call the repaint method but the rectangle doesn't move at all - therefore I am probably messing up something with the KeyEvent and/or with repaint.
为此,我将与箭头相关联的更改x位置的方法称为repaint方法,但矩形根本不移动-因此,我可能将KeyEvent和/或repaint弄乱了。
What should I do to make the rectangle each time I press the proper arrow key move and refresh the Panel ? 每次按适当的箭头键移动并刷新面板时,应该怎么做才能使矩形变为矩形?
public class Car extends JPanel {
int x;
int y;
public Car(int x,int y){
this.x=x;
this.y=y;
}
public void paint(Graphics g) {
g.setColor(Color.RED);
g.fillRect(x, y, 20, 20);
}
public void move_right(){
x=x+20;
}
public void move_left(){
x=x-20;
}
}
public class Form extends JFrame {
//private JPanel contentPane;
Car car1;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Form frame = new Form();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Form() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 727, 550);
getContentPane().setLayout(null);
car1 = new Car(350, 480);
car1.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_KP_LEFT) {
car1.move_left();
car1.repaint();
}
if (key == KeyEvent.VK_KP_RIGHT) {
car1.move_right();
car1.repaint();
}
}
});
car1.setBounds(0, 0, 700, 500);
car1.setBackground(new Color(255, 255, 255));
getContentPane().add(car1);
}
}
There are at least 3 problems: 至少有3个问题:
KeyListener
. KeyListener
。 KeyListener
is well known for only responding to key events which occur on components which are focusable AND have keyboard focus. KeyListener
是众所周知的,它仅响应可聚焦且具有键盘焦点的组件上发生的键事件。 A JPanel
by default is not focusable, therefore it can't recieve keyboard focus. JPanel
不能聚焦,因此无法接收键盘焦点。 A better solution is to use the key bindings API, which allows to define the level of focus a component must have before the bindings are triggered and allows you to re-use a Action
for multiple keys, reducing code duplication Action
用于多个键,从而减少代码重复 paint
. paint
。 It's highly recommended to override paintComponent
instead of paint when performing custom painting. paintComponent
而不是paint。 You've also failed to maintain the paint chain, which is going to cause no end of weird and wonderful paint artifacts. null
layouts. null
布局。 Avoid using null
layouts, pixel perfect layouts are an illusion within modern ui design. null
布局,像素完美布局是现代ui设计中的一种幻觉。 There are too many factors which affect the individual size of components, none of which you can control. For example... 例如...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
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.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 (Exception 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 class TestPane extends JPanel {
private int xPos;
public TestPane() {
Action leftAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
xPos -= 2;
if (xPos < 0) {
xPos = 0;
}
repaint();
}
};
Action rightAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
xPos += 2;
if (xPos + 10 > getWidth()) {
xPos = getWidth() - 10;
}
repaint();
}
};
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), leftAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_KP_LEFT, 0), leftAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_4, 0), leftAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), leftAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), rightAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_KP_RIGHT, 0), rightAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_6, 0), rightAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), rightAction);
}
protected void bindKeyStroke(int condition, String name, KeyStroke keyStroke, Action action) {
InputMap im = getInputMap(condition);
ActionMap am = getActionMap();
im.put(keyStroke, name);
am.put(name, action);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int yPos = (getHeight() - 10) / 2;
g2d.drawRect(xPos, yPos, 10, 10);
g2d.dispose();
}
}
}
This is a solution: 这是一个解决方案:
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
car1.move_left();
car1.repaint();
}
if (key == KeyEvent.VK_RIGHT) {
car1.move_right();
car1.repaint();
}
}
});
Where are the mistakes: 错误在哪里:
addKeyListener
: add key listener to frame, not to panel addKeyListener
:将关键侦听器添加到框架,而不是面板 VK_KP_
: use VK_
prefix instead VK_KP_
:改为使用VK_
前缀 keyTyped
: use keyPressed
instead keyTyped
:改用keyPressed
Next step you will have to solve is removing the previous rectangles 您必须解决的下一步是删除先前的矩形
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.