我一直在尝试编写一个小型的侧卷轴游戏,但遇到了重绘()没有重新绘制的问题。键侦听器本身可以工作,它在按下方向键时递增和递减x和y值。只是重绘()似乎没有重新粉刷。
public class SideScroller extends JPanel implements KeyListener{
private Random random = new Random();
private int r,g,b;
private int x = 0, y = 0;
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == e.VK_UP) {
y -= 5;
} else if(e.getKeyCode() == e.VK_DOWN) {
y += 5;
} else if(e.getKeyCode() == e.VK_LEFT) {
x -= 5;
} else if(e.getKeyCode() == e.VK_RIGHT) {
x += 5;
}
repaint();
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
public void paint(Graphics gg) {
gg.setColor(new Color(r, g, b));
gg.fillRect (x, y, 50, 50);
}
public static void main(String[] args) {
SideScroller ss = new SideScroller();
JFrame f = new JFrame();
f.add(new SideScroller());
f.setSize(500, 500);
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
f.addKeyListener(new SideScroller());
}
答案 0 :(得分:1)
您应该覆盖paintComponent
并致电super.paintComponent
,而不是paint
。
protected void paintComponent(Graphics gg) {
super.paintComponent(gg);
gg.setColor(new Color(r, g, b));
gg.fillRect (x, y, 50, 50);
}
此外,我建议您使用Key Bindings代替KeyListener
,
此外,您应该在Event Dispacth线程上运行Swing应用程序您可以将代码包装在main
SwingUtilities.invokeLater(...)
中。
以下是上面提到的所有修复
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class SideScroller extends JPanel {
private Random random = new Random();
private int r, g, b;
private int x = 0, y = 0;
public SideScroller() {
InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke("UP"), "upaction");
am.put("upaction", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
y -= 5;
repaint();
}
});
im.put(KeyStroke.getKeyStroke("DOWN"), "downaction");
am.put("downaction", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
y += 5;
repaint();
}
});
im.put(KeyStroke.getKeyStroke("LEFT"), "leftaction");
am.put("leftaction", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
x -= 5;
repaint();
}
});
im.put(KeyStroke.getKeyStroke("RIGHT"), "rightaction");
am.put("rightaction", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
x += 5;
repaint();
}
});
}
protected void paintComponent(Graphics gg) {
super.paintComponent(gg);
gg.setColor(new Color(r, g, b));
gg.fillRect(x, y, 50, 50);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.add(new SideScroller());
f.setSize(500, 500);
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}
答案 1 :(得分:1)
对于原始海报和Boann:使用Swing Timer示例进行键绑定:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
public class GamePanel extends JPanel {
private static final int ANIMATION_DELAY = 15;
private final int HEIGHT = 400;
private final int WIDTH = 600;
private Square square;
private EnumMap<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
private Map<Integer, Direction> keyToDir = new HashMap<>();
private Timer animationTimer;
public GamePanel() {
for (Direction dir : Direction.values()) {
dirMap.put(dir, Boolean.FALSE);
}
keyToDir.put(KeyEvent.VK_UP, Direction.UP);
keyToDir.put(KeyEvent.VK_DOWN, Direction.DOWN);
keyToDir.put(KeyEvent.VK_LEFT, Direction.LEFT);
keyToDir.put(KeyEvent.VK_RIGHT, Direction.RIGHT);
setKeyBindings();
setBackground(Color.white);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
square = new Square();
animationTimer = new Timer(ANIMATION_DELAY, new AnimationListener());
animationTimer.start();
}
private void setKeyBindings() {
int condition = WHEN_IN_FOCUSED_WINDOW;
final InputMap inputMap = getInputMap(condition);
final ActionMap actionMap = getActionMap();
boolean[] keyPressed = { true, false };
for (Integer keyCode : keyToDir.keySet()) {
Direction dir = keyToDir.get(keyCode);
for (boolean onKeyPress : keyPressed) {
boolean onKeyRelease = !onKeyPress;
KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, 0,
onKeyRelease);
Object key = keyStroke.toString();
inputMap.put(keyStroke, key);
actionMap.put(key, new KeyBindingsAction(dir, onKeyPress));
}
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
square.display(g);
}
private class AnimationListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
boolean repaint = false;
for (Direction dir : Direction.values()) {
if (dirMap.get(dir)) {
square.move(dir);
repaint = true;
}
}
if (repaint) {
repaint();
}
}
}
private class KeyBindingsAction extends AbstractAction {
private Direction dir;
boolean pressed;
public KeyBindingsAction(Direction dir, boolean pressed) {
this.dir = dir;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent evt) {
dirMap.put(dir, pressed);
}
}
private static void createAndShowGUI() {
GamePanel gamePanel = new GamePanel();
JFrame frame = new JFrame("GamePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(gamePanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
gamePanel.requestFocusInWindow();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
enum Direction {
UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0);
private int incrX;
private int incrY;
private Direction(int incrX, int incrY) {
this.incrX = incrX;
this.incrY = incrY;
}
public int getIncrX() {
return incrX;
}
public int getIncrY() {
return incrY;
}
}
class Square {
private int x = 0;
private int y = 0;
private int w = 20;
private int h = w;
private int step = 1;
private Color color = Color.red;
private Color fillColor = new Color(255, 150, 150);
private Stroke stroke = new BasicStroke(3f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND);
public void display(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(fillColor);
g2d.fillRect(x, y, w, h);
g2d.setStroke(stroke);
g2d.setColor(color);
g2d.drawRect(x, y, w, h);
g2d.dispose();
}
public void setStep(int step) {
this.step = step;
}
public void move(Direction dir) {
x += step * dir.getIncrX();
y += step * dir.getIncrY();
}
}
答案 2 :(得分:0)
这里的问题是两件事。您正在将键侦听器添加到新 SideScroller - 与您渲染的不同,并且您不会覆盖正确的绘制方法。
我建议您将addKeyListener(this);
添加到SideScroller的构造函数中并删除f.addKeyListener(new SideScroller());
,测试即被调用然后测试应该为paintComponent(Graphics g)
的绘制方法。
我希望你明白如何做到这一点,以及为什么要识别密钥,但不是&#39;渲染,我不相信为初学者提供代码是个好主意。
答案 3 :(得分:0)
您正在创建三个不同的SideScroller对象。一个未使用的,第二个,您添加到框架并显示,第三个,您只用作KeyListener(调用repaint()方法)。您放入ss
变量的SideScroller也应该添加到框架中并用作KeyListener。