如何使用 KeyListener 在 JFrame 中移动一个矩形?
How to move move a rectangle in JFrame using KeyListener?
我试图让我的 JFrame 中的一个矩形在我按下键盘上的给定键时移动,但我似乎很难做到这一点。这是我的代码:
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 的问题,因为其他一切正常。有人知道我做错了什么吗?谢谢
像这样制作你的 main 就可以了
public static void main (String[] args)
{
JFrame frame = new JFrame ("Mainframe");
JComponent test = new Mainframe();
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setSize (800, 600);
frame.setFocusable (true);
frame.getContentPane().setBackground (Color.WHITE);
frame.getContentPane().add (test);
frame.addKeyListener ((KeyListener) test);
frame.setVisible (true);
}
- 您正在创建
MainFrame
的两个实例,一个添加到框架中,另一个用作 JFrame
的 KeyListener
,这意味着对 KeyListener
实例生成 x/y
值,不会被 UI 上的实例看到
- 不要使用
KeyListener
,它有太多与焦点相关的问题,请使用专为克服这些问题而设计的键绑定 API。参见 How to Use Key Bindings
- 不要覆盖
paint
(特别是如果您不打算调用 super.paint
),相反,您应该覆盖 paintComponent
方法(并调用 super.paintComponent
).有关详细信息,请参阅 Painting in AWT and Swing and Performing Custom Painting
- 确保您仅在事件调度线程的上下文中创建和修改 UI,有关详细信息,请参阅 Initial Threads
例如...
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();
}
}
}
我试图让我的 JFrame 中的一个矩形在我按下键盘上的给定键时移动,但我似乎很难做到这一点。这是我的代码:
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 的问题,因为其他一切正常。有人知道我做错了什么吗?谢谢
像这样制作你的 main 就可以了
public static void main (String[] args)
{
JFrame frame = new JFrame ("Mainframe");
JComponent test = new Mainframe();
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setSize (800, 600);
frame.setFocusable (true);
frame.getContentPane().setBackground (Color.WHITE);
frame.getContentPane().add (test);
frame.addKeyListener ((KeyListener) test);
frame.setVisible (true);
}
- 您正在创建
MainFrame
的两个实例,一个添加到框架中,另一个用作JFrame
的KeyListener
,这意味着对KeyListener
实例生成x/y
值,不会被 UI 上的实例看到
- 不要使用
KeyListener
,它有太多与焦点相关的问题,请使用专为克服这些问题而设计的键绑定 API。参见 How to Use Key Bindings - 不要覆盖
paint
(特别是如果您不打算调用super.paint
),相反,您应该覆盖paintComponent
方法(并调用super.paintComponent
).有关详细信息,请参阅 Painting in AWT and Swing and Performing Custom Painting - 确保您仅在事件调度线程的上下文中创建和修改 UI,有关详细信息,请参阅 Initial Threads
例如...
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();
}
}
}