На самом деле, это мой ответ: убрать рандомизацию из вашего кода рисования. Вместо этого дайте классу Cell метод, скажем, с именем randomize()
, который выполняет рандомизацию цветов и вызывается только тогда, когда вы хотите, чтобы он вызывался, и удалите этот код из кода рисования.
Почему это важно? Поймите, что при использовании Swing отрисовка не полностью находится под вашим контролем, что вы можете предложить отрисовку, вызвав repaint()
, но это не гарантируется всегда (особенно если запросы на перерисовку "стекаются"), а также иногда ОС сделает запрос к JVM о том, что происходит рисование, и это полностью вне вашего контроля. Так что методы рисования должны делать только рисование и ничего больше. Любой код, который значительно изменяет состояние ваших объектов, например код рандомизации, принадлежит другому месту.
Например:
import java.awt.*;
import java.util.Random;
public class Cell extends Rectangle {
// no magic numbers
private static final Color DIRT_COLOR = new Color(102, 51, 0);
private static final Color GRASS_COLOR = new Color(102,153,0);
private static final Color TREE_COLOR = new Color(0, 102, 0);
private static final Color ROCK_COLOR = new Color(182, 182, 182);
private static final int CELL_WIDTH = 35;
private static final int RECT_WIDTH = CELL_WIDTH - 1;
private Color cellColor = null;
private Random random;
public Cell(int x, int y) {
super(x, y, CELL_WIDTH, CELL_WIDTH);
}
// highlighted should be a boolean primitive, not a Boolean wrapper
public void paint(Graphics g, boolean highlighted) {
int row;
int col;
// **** these nested for loops don't look right
// as this Cell should draw itself and only itself
for (row = 0; row < 20; row++) {
for (col = 0; col < 20; col++) {
x = col * CELL_WIDTH;
y = row * CELL_WIDTH;
// don't call surfactType() here, but rather *****
// simply draw with cellColor *******
if (cellColor != null) {
g.setColor(cellColor);
g.fillRect(x, y, RECT_WIDTH, RECT_WIDTH);
}
}
}
g.setColor(Color.BLACK);
g.drawRect(x, y, CELL_WIDTH, CELL_WIDTH);
if (highlighted) {
g.setColor(Color.LIGHT_GRAY);
g.fillRect(x, y, CELL_WIDTH, CELL_WIDTH);
} else {
g.setColor(Color.DARK_GRAY);
g.fillRect(x, y, CELL_WIDTH, CELL_WIDTH);
}
}
@Override
public boolean contains(Point target) {
if (target == null)
return false;
return super.contains(target);
}
// ** Rename this from SurfaceType to surfaceType
public void surfaceType() {
random = new Random();
int randomNumber = random.nextInt(5);
switch (randomNumber) {
case 1: // dirt
cellColor = DIRT_COLOR;
break;
case 2: // grass
cellColor = GRASS_COLOR;
break;
case 3: // tree
cellColor = TREE_COLOR;
break;
case 4: // rock
cellColor = ROCK_COLOR;
break;
}
}
}
Теперь ваш код GUI может вызывать surfaceType()
для рандомизации ячейки, когда это необходимо, и вызывать repaint()
после изменения состояния. Случайная картина не изменит состояние ячейки.
Другие несвязанные проблемы с вашим кодом:
- Ваш метод рисования с вложенным циклом for пытается закрасить все ячейки, а не только текущую, и это выглядит неправильно. Вместо этого он должен заниматься только самой живописью.
- Ваш код не полностью соответствует соглашениям об именах Java, поскольку имена методов должны начинаться со строчной буквы.
- Вы используете много «магических» чисел и значений и хотите избежать этого, чтобы сделать свой код гораздо более самокомментирующим.
Возможно, чище было бы что-то в этом роде, используя enum для вашего Ground:
import java.awt.Color;
public enum Ground {
DEFAULT(null), // Not sure if you need a default
DIRT(new Color(102, 51, 0)),
GRASS(new Color(102,153,0)),
TREE(new Color(0,102,0)),
ROCK(new Color(182,182,182));
private Ground(Color color) {
this.color = color;
}
private Color color;
public Color getColor() {
return color;
}
public static Ground getRandom() {
int randomIndex = (int) (Math.random() * Ground.values().length);
return Ground.values()[randomIndex];
}
}
и для Cell2
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
public class Cell2 {
private static final int CELL_WIDTH = 35;
private static final Stroke STROKE = new BasicStroke(3f);
private Rectangle rect; // favor composition over inheritance
private Ground ground;
public Cell2(int x, int y) {
rect = new Rectangle(x, y, CELL_WIDTH, CELL_WIDTH);
}
public void paint(Graphics2D g2, boolean highlighted) {
if (ground != null && ground != Ground.DEFAULT) {
g2.setColor(ground.getColor());
g2.fill(rect);
}
g2.setStroke(STROKE);
Color c = highlighted ? Color.LIGHT_GRAY : Color.DARK_GRAY;
g2.setColor(c);
g2.draw(rect);
}
public void randomizeGround() {
ground = Ground.getRandom();
}
public boolean contains(Point p) {
return rect.contains(p);
}
}
person
Hovercraft Full Of Eels
schedule
26.08.2017
paint
выше, который предположительно вызывается в методе рисования в графическом интерфейсе, содержит в себе некоторую программную логику, код для выполнения рандомизации. Поймите, что рандомизация должна выполняться не в коде отрисовки, а в другом месте, чтобы на нее не влияли перерисовки, которые находятся вне вашего контроля. - person Hovercraft Full Of Eels   schedule 26.08.2017x
иy
в части цикла; поэтому независимо от того, какое предыдущее значение вы установили для них, к тому времени, когда вы закончите часть случайного цвета, они всегда будут установлены в правом нижнем углу экрана. - person meowgoesthedog   schedule 26.08.2017