fillOval() 在 if 语句中不起作用[关闭]
Posted
技术标签:
【中文标题】fillOval() 在 if 语句中不起作用[关闭]【英文标题】:fillOval() not working inside a if statement [closed] 【发布时间】:2022-01-22 02:11:56 【问题描述】:我正在构建一个贪吃蛇游戏,但遇到了问题。我希望只画一次 10 个水果,但我需要更新蛇的位置,所以我添加了一个 if 语句,但 fillOval() 方法不起作用。我通过删除 for 循环和 if 语句对其进行了测试,它工作得很好。代码如下:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SnakeFrame extends JPanel implements ActionListener
boolean hasPaintedFruits;
SnakeFrame()
JFrame frame = new JFrame("Snake Game");
frame.setSize(800,600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
hasPaintedFruits = false;
Timer t = new Timer(16, this);
t.restart();
frame.add(this);
frame.setVisible(true);
@Override
public void paintComponent(Graphics g)
super.paintComponent(g);
if(!hasPaintedFruits)
new Fruit().paint(g);
hasPaintedFruits = true;
new Fruit().paint(g);
Snake sHead = new Snake();
sHead.paint(g);
@Override
public void actionPerformed(ActionEvent e)
repaint();
import java.awt.*;
import java.util.Random;
public class Fruit
//pos
int x, y;
Fruit()
Random random = new Random();
x = random.nextInt(800);
y = random.nextInt(600);
public void paint(Graphics g)
g.setColor(Color.RED);
g.fillOval(x,y,10,10);
【问题讨论】:
您发布的代码中的fillOval(...)
调用在哪里?
另外,Fruit 类是扩展 Swing 组件的类吗?如果是这样,您不应该在paint 中创建实例或直接调用paint 方法。
另外,paint
方法不应调用super.paintComponent
,因为这会破坏绘制链。它应该调用super.paint
。更好的是,你应该覆盖paintComponent
,而不是paint。
Fruit 类没有扩展 Swing 组件。让我在这里发布该类的代码
您的绘图方法中似乎有程序逻辑代码,可以更改您的 Swing 组件的状态,这是不明智的。逻辑应该在你的 Swing Timer 中,而绘制方法(应该是 paintComponent
覆盖)应该只根据对象的状态进行绘制,仅此而已。
【参考方案1】:
您的目标是绘制一次,解决方案是摆脱 if 块,并在 paintComponent 方法中简单地绘制需要绘制的内容。例如,假设您有一个带有 x 和 y 位置的 Fruit2 类以及一个 draw 方法:
class Fruit2
private static final Color FRUIT_COLOR = Color.BLUE.brighter();
public static final int FRUIT_SIDE = 20;
private int x, y;
public Fruit2(int x, int y)
this.x = x;
this.y = y;
public void draw(Graphics g)
g.setColor(FRUIT_COLOR);
g.fillRect(x, y, FRUIT_SIDE, FRUIT_SIDE);
比如说,主绘图类包含一个包含 10 个这些项目的数组:
private static final int FRUIT_COUNT = 10;
//.....
private Fruit2[] fruits = new Fruit2[FRUIT_COUNT];
假设绘图 JPanel 也有一个 Snake2 对象,该对象也有一个 draw 方法(知道如何绘制自己),那么您的 paintComponent 方法将很简单:
@Override
protected void paintComponent(Graphics g)
super.paintComponent(g);
for (Fruit2 fruit : fruits)
fruit.draw(g);
snake.draw(g);
就是这样。 Fruit2 对象自己绘制自己,而蛇自己绘制自己——完成。
同样,正如我在上面的 cmets 中所提到的,绘画方法不应该包含移动蛇的代码 - 将其留给计时器的 ActionListener。相反,绘画方法,这里 paintComponent(...)
只是绘制 GUI 状态的表示,仅此而已。
作为我的意思的一个有效示例,请运行以下代码:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class SnakePanel2 extends JPanel
private static final long serialVersionUID = 1L;
private static final int PANEL_WIDTH = 800;
private static final int PANEL_HEIGHT = 650;
private static final int TIMER_DELAY = 40;
private static final Color BG = Color.WHITE;
private static final int FRUIT_COUNT = 10;
private Snake2 snake = new Snake2(PANEL_WIDTH, PANEL_HEIGHT);
private Fruit2[] fruits = new Fruit2[FRUIT_COUNT];
public SnakePanel2()
setBackground(BG);
new Timer(TIMER_DELAY, e -> timerStep()).start();
for (int i = 0; i < fruits.length; i++)
int x = (int) ((PANEL_WIDTH - Fruit2.FRUIT_SIDE) * Math.random());
int y = (int) ((PANEL_HEIGHT - Fruit2.FRUIT_SIDE) * Math.random());
fruits[i] = new Fruit2(x, y);
private void timerStep()
snake.move();
repaint();
@Override
protected void paintComponent(Graphics g)
super.paintComponent(g);
for (Fruit2 fruit : fruits)
fruit.draw(g);
snake.draw(g);
@Override
public Dimension getPreferredSize()
return new Dimension(PANEL_WIDTH, PANEL_HEIGHT);
public static void main(String[] args)
SwingUtilities.invokeLater(() ->
SnakePanel2 panel = new SnakePanel2();
JFrame frame = new JFrame("Snake Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
);
class Fruit2
private static final Color FRUIT_COLOR = Color.BLUE.brighter();
public static final int FRUIT_SIDE = 20;
private int x, y;
public Fruit2(int x, int y)
this.x = x;
this.y = y;
public void draw(Graphics g)
g.setColor(FRUIT_COLOR);
g.fillRect(x, y, FRUIT_SIDE, FRUIT_SIDE);
class Snake2
private static final int MAX_POINTS = 60;
private static final int RADIUS = 8;
private static final int DELTA = 8;
private static final int DIRECTION_STEPS = 16;
private static final int DIR_MAX_DELTA = 2;
private static final Point2D[] DIRECTION_ARRAY = new Point2D[DIRECTION_STEPS];
private static final Color SNAKE_COLOR = Color.RED;
private List<Point2D> units = new ArrayList<>();
private int currentDirection = (DIRECTION_STEPS * 3) / 8;
private int maxWidth;
private int maxHeight;
static
for (int i = 0; i < DIRECTION_ARRAY.length; i++)
double x = DELTA * Math.cos((2 * Math.PI * i) / DIRECTION_ARRAY.length);
double y = DELTA * Math.sin((2 * Math.PI * i) / DIRECTION_ARRAY.length);
DIRECTION_ARRAY[i] = new Point2D.Double(x, y);
public Snake2(int maxWidth, int maxHeight)
this.maxWidth = maxWidth;
this.maxHeight = maxHeight;
units.add(new Point2D.Double(0, 0));
public void move()
if (units.size() != 1)
currentDirection += (2 * DIR_MAX_DELTA + 1) * (Math.random()) - DIR_MAX_DELTA;
currentDirection += DIRECTION_STEPS;
currentDirection %= DIRECTION_STEPS;
double x = units.get(0).getX() + DIRECTION_ARRAY[currentDirection].getX();
double y = units.get(0).getY() + DIRECTION_ARRAY[currentDirection].getY();
if (x < 0)
x += maxWidth;
else if (x > maxWidth)
x -= maxWidth;
if (y < 0)
y += maxHeight;
else if (y > maxHeight)
y -= maxHeight;
units.add(0, new Point2D.Double(x, y));
if (units.size() >= MAX_POINTS)
units.remove(units.size() - 1);
public void draw(Graphics g)
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(SNAKE_COLOR);
for (Point2D unit : units)
double x = unit.getX() - RADIUS;
double y = unit.getY() - RADIUS;
double w = 2 * RADIUS;
double h = w;
Ellipse2D e2d = new Ellipse2D.Double(x, y, w, h);
g2.fill(e2d);
g2.dispose();
【讨论】:
感谢您的帮助!不幸的是,它仍然没有被绘制一次。每次调用paintComponent()
方法时,都会重新绘制水果以上是关于fillOval() 在 if 语句中不起作用[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
基本的 If else 语句在 javascript 中不起作用
比较 Mongoose 对象 ID 时,if 语句在 Jade 中不起作用