简体   繁体   中英

JAVA - Creating a Row of Colored Boxes with Loops?

I'm a beginner with graphics, as well as Java all together. It seems that no matter what I do, this program is not working! :( Anyway, the goal is to "Use nested loops, Graphics, and Math.random() to print out the square pattern" The pattern is 30x30 squares next to each other in 14 rows by 20 columns. Here is my code so far:

 import java.awt.Color; import java.awt.Font; import java.awt.Canvas; class ColoredBoxes extends Canvas { public ColoredBoxes() { setBackground(Color.BLACK); } public void paint( Graphics window ) { window.setColor(Color.RED); window.setFont(new Font("TAHOMA",Font.BOLD,12)); window.drawString("**Fun Fact: I hate snow.**", 20, 40 ); window.drawString("Drawing boxes with nested loops ", 20, 80 ); //private static final int WIDTH = 800; //private static final int HEIGHT = 600; //Boxes: 20 Across, 14 Down drawBoxes(window); } public void drawBoxes(Graphics window) { //nested loops to draw the pretty boxes //int drawRow = 1; //int drawCol = 1; int c1 = (int)(Math.random()*256); int c2 = (int)(Math.random()*256); int c3 = (int)(Math.random()*256); Color random = new Color (c1,c2,c3); int dS = 30; //Distance from the side (left) int dT = 100; //Distance from the top int x = 30; //Width int y = 30; //Height for(int drawRow = 1; drawRow <= 14; drawRow++) { for(int drawCol = 1; drawCol <= 20; drawCol++) { window.setColor(Color.white); window.fillRect(dS, dT, x, y); window.setColor(Color.black); window.drawRect(dS, dT, x, y); System.out.println(); dS = dS+y; } dT = dT+x; } } } 

Each square should also be a different, random color. What did I do wrong? Thank you so much :)

Start by taking a look through Performing Custom Painting and Painting in AWT and Swing for details about painting actually works.

You don't control the paint process, this means that painting may occur at any time for any reason, many of which are outside of your control. This means, that each time drawBoxes is called, you are generating new colors.

Painting is also made up of a chain of method calls, which helps provide better customisation opportunities, but you are breaking this paint chain by not calling super.paint first.

What I would do is first create a List or array of colors, which represent each individual cell in your grid. I would use this each time paint was called to ensure that the painting was consistent

漂亮网格

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ColoredBoxes {

    public static void main(String[] args) {
        new ColoredBoxes();
    }

    public ColoredBoxes() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        protected static final int ROWS = 14;
        protected static final int COLS = 20;
        protected static final int BOX_SIZE = 30;

        private List<Color> colors;

        public TestPane() {
            int length = ROWS * COLS;
            colors = new ArrayList<>(length);
            for (int index = 0; index < length; index++) {
                int c1 = (int) (Math.random() * 255);
                int c2 = (int) (Math.random() * 255);
                int c3 = (int) (Math.random() * 255);
                colors.add(new Color(c1, c2, c3));
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
            int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;

            System.out.println("...");
            for (int row = 0; row < ROWS; row++) {
                for (int col = 0; col < COLS; col++) {
                    int index = (row * COLS) + col;
                    g2d.setColor(colors.get(index));
                    g2d.fillRect(xOffset + (col * BOX_SIZE), 
                                    yOffset + (row * BOX_SIZE), 
                                    BOX_SIZE, BOX_SIZE);
                }
            }
            g2d.dispose();
        }

    }

}

Updated

The basic problem revolves around how you are calculating the row/col position for each cell and the misuse of the Graphics#draw/fillRectangle method.

While you could simply increment the x/y position of each grid within the for-loop , a simpler approach would be to simply calculate them based on your current row/col

int xOffset = 50;
int yOffset = 100;
for (int drawRow = 0; drawRow < 14; drawRow++) {
    for (int drawCol = 0; drawCol < 20; drawCol++) {
        int x = drawCol * 30 + xOffset;
        int y = (drawRow * 30) + yOffset;

The next issue is the misuse of Graphics#draw/fillRect . The JavaDocs state that

public abstract void fillRect(int x,
int y,
int width,
int height)

Fills the specified rectangle. The left and right edges of the rectangle are at x and x + width - 1. The top and bottom edges are at y and y + height - 1. The resulting rectangle covers an area width pixels wide by height pixels tall. The rectangle is filled using the graphics context's current color.


x - the x coordinate of the rectangle to be filled.
y - the y coordinate of the rectangle to be filled.
width - the width of the rectangle to be filled.
height - the height of the rectangle to be filled.

This means that last two parameters should be 30, 30 , not what ever you're currently passing to them.

Also you MUST call super.paint(window); before you perform any custom painting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM