Почему созданная мной точка не движется?
Я пытаюсь переместить точку, нажимая клавиши вправо-влево. Вот мой главный:
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setSize(500,500);
Graphic graphic=new Graphic();
frame.add(graphic);
}}
Это графический класс, в котором я создал точку и реализовал KeyListener и ActionListener:
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.JPanel;
import javax.swing.Timer;
public class Graphic extends JPanel implements ActionListener, KeyListener {
private int posX = 220;
private int posY = 300;
private Timer timer;
private int delay = 8;
private int width = 500;
private int height = 500;
public Graphic() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
timer = new Timer(delay, this);
timer.start();
this.setSize(width, height);
}
public void paint(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, width, height);
g.setColor(Color.GREEN);
g.fillOval(posX, posY, 20, 20);
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
if (posX <= 20) {
posX = 20;
} else {
moveLeft();
}
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
if (posX >= 460) {
posX = 460;
} else {
moveRight();
}
}
repaint();
}
private void moveRight() {
posX += 20;
}
private void moveLeft() {
posX -= 20;
}
@Override
public void actionPerformed(ActionEvent e) {
timer.start();
repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
На мой взгляд, это должно работать... но это не так. Когда я нажимаю левую и правую клавиши, ничего не происходит, и похоже, что он не "слушает" мои команды. Итак, что не так с моим кодом?
2 ответа
KeyListener
работает, если компонент, имеющий слушателя, имеет фокус.
JFrame по умолчанию имеет фокус при отображении, но не JPanel.
в Graphic
конструктор добавить просто grabFocus()
:
public Graphic() {
addKeyListener(this);
setFocusTraversalKeysEnabled(true);
setFocusable(true);
grabFocus();
timer = new Timer(delay, this);
timer.start();
this.setSize(width, height);
}
РЕДАКТИРОВАТЬ
Я проверил на моей машине. Проблема в том, что он работает случайным образом, так как JFrame должен быть видимым, если мы хотим, чтобы JPanel захватил фокус. Иногда это так, а иногда нет. SwingUtilities.invokeLater()
может решить проблему.
После добавления панели в JFrame
, вызвать код, который захватывает фокус в invokeLater()
метод.
frame.add(graphic);
...
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
graphic.grabFocus();
}
});
Ты звонишь repaint
метод Component
класс вместо вашего paint
метод.