如何阻止网格单元在Java中重绘?

时间:2017-08-26 20:48:38

标签: java random graphics colors grid

我正在尝试为网格中的每个单元格生成随机颜色(4种颜色之间)。我已设法这样做,但它不断重绘网格的轮廓和网格的其他元素。我怎样才能使颜色只画一次?,而我的其他元素一直在画画? 这是我目前的代码:

import java.awt.*;
import java.util.Random;

public class Cell extends Rectangle {

private Random random;

public Cell(int x, int y) {

    super(x, y, 35, 35);
}


public void paint(Graphics g, Boolean highlighted) {

    int row;
    int col;

    for (row=0; row < 20 ; row++ ) {
        for (col =0; col <20 ; col++) {
            x=col * 35;
            y=row * 35;
            SurfaceType(g);
        }
    }


    g.setColor(Color.BLACK);
    g.drawRect(x, y, 35, 35);


    if (highlighted) {
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(x, y, 35, 35);
    } else {
        g.setColor(Color.DARK_GRAY);
        g.fillRect(x, y, 35, 35);
    }

}



@Override
public boolean contains(Point target){
    if (target == null)
        return false;
    return super.contains(target);
}

public void SurfaceType(Graphics g) {
   random= new Random();
   int randomNumber = random.nextInt( 5);

   switch (randomNumber) {
       case 1: // dirt
           g.setColor(new Color(102,51,0));
           g.fillRect(x,y,34,34);
           break;
       case 2: //grass
           g.setColor(new Color(102,153,0));
           g.fillRect(x,y,34,34);
           break;
       case 3: //tree
           g.setColor(new Color(0,102,0));
           g.fillRect(x,y,34,34);
           break;
       case 4: //rock
           g.setColor(new Color(182,182,182));
           g.fillRect(x,y,34,34);
           break;
   }



 }


}

此图显示当我取出随机化颜色的代码时网格的样子。

enter image description here

这一部分代码包括:

enter image description here

1 个答案:

答案 0 :(得分:1)

事实上,这是我的答案:采用绘画代码的随机化 out 。相反,给Cell类一个方法,比如称为randomize(),它执行颜色的随机化,只在你想要它被调用时被调用,并从你的绘画代码中删除那些代码。

为什么这很重要?了解到使用Swing,绘画并不完全在您的控制之下,您可以通过调用repaint()建议绘画,但不能保证总是会发生(特别是如果重新绘制请求) &#34; stack&#34;),有时操作系统会向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循环的paint方法似乎试图绘制所有单元格而不仅仅是当前单元格,这看起来并不正确。相反,它应该只涉及绘画本身。
  • 您的代码并不完全遵循Java命名约定,因为方法名称应以小写字母开头。
  • 你正在使用很多&#34;魔法&#34;数字和值,并希望避免这样做,以使您的代码更自我评论。

也许更干净的东西就是这样,使用枚举为你的地面:

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);
    }
}