Question

I have a class called DrawRectangles that takes an array of integers.

What I am trying to do is go through the numbers in the array and for each one, create a new panel using the number in the array as the panel's width and X position.

Let's say I pass in [2, 4, 6, 8]. I want to create a new panel to add to the JFrame with each of these numbers.

So the first panel should start at position 2 and have a width of 2. I also have a random color generator which is supposed to create a new color for each panel. Here is what I have:

public class DrawRectangles {
    JFrame frame;
    DrawPanel panel;
    Random randomGenerator = new Random();
    int red = randomGenerator.nextInt(255);
    int green = randomGenerator.nextInt(255);
    int blue = randomGenerator.nextInt(255);
    Color randomColor;
    int[] newWidth;

    DrawRectangles(int[] width){
        this.newWidth = width;
    }

    public void setUpFrame(){
        frame = new JFrame();
        frame.setSize(500,100);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        for(int x = 0; x < newWidth.length; x++){
            panel = new DrawPanel(newWidth[x]);
            frame.add(panel);
        }
    }
    class DrawPanel extends JPanel{
        int newWidth;
        DrawPanel(int width){
            this.newWidth = width;
            System.out.println(newWidth);
        }
        public void paint(Graphics g) {
           super.paint(g);
           randomColor = new Color(red,green,blue);
           g.setColor(randomColor);
           g.fillRect(newWidth, 10, newWidth, 30);
        }
    }
}
Was it helpful?

Solution

You have a number of issues...

  • Frame uses a BorderLayout by default. This will only allow a single component to occupy any one of the pre-defined position available to it. This means that only the last pane will be visible.
  • You don't control the paint process. This means that every time randomColor changes values, all the components referencing it will also be repainted with it on the next paint cycle.
  • You should be using paintComponent instead of paint

This is a basic example using a single DrawRectangle component to paint all the rectangles.

enter image description here

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

public class DrawRectangles {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                DrawRectangles dr = new DrawRectangles(new int[]{2, 4, 6, 8});
                dr.setUpFrame();

            }
        });
    }

    JFrame frame;
    DrawPanel panel;
    Random randomGenerator = new Random();
    int[] newWidth;

    DrawRectangles(int[] width) {
        this.newWidth = width;
    }

    public void setUpFrame() {
        frame = new JFrame();
        frame.setSize(500, 100);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        DrawPanel panel = new DrawPanel();
        for (int x = 0; x < newWidth.length; x++) {
            int red = randomGenerator.nextInt(255);
            int green = randomGenerator.nextInt(255);
            int blue = randomGenerator.nextInt(255);
            panel.addRectangle(new Color(red, green, blue), newWidth[x]);
        }
        frame.setSize(200, 200);
        frame.add(panel);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public class MyRectangle {

        private Color color;
        private Rectangle rectangle;

        public MyRectangle(Color color, int width) {
            this.color = color;
            rectangle = new Rectangle(width, 10, width, 30);
        }

        public Color getColor() {
            return color;
        }

        public Rectangle getRectangle() {
            return rectangle;
        }

        public void draw(Graphics2D g2d) {
            g2d.setColor(color);
            g2d.fill(rectangle);
        }
    }

    public class DrawPanel extends JPanel {

        private List<MyRectangle> rectangles;

        public DrawPanel() {
            rectangles = new ArrayList<>();
        }

        public void addRectangle(Color color, int width) {
            rectangles.add(new MyRectangle(color, width));
        }

        public void paint(Graphics g) {
            super.paint(g);
            Graphics2D g2d = (Graphics2D) g.create();
            for (MyRectangle rect : rectangles) {
                rect.draw(g2d);
            }
            g2d.dispose();
        }
    }
}

You could use a different layout manager, but then your DrawRectangle component must also return a preferredSize so that the layout manager doesn't layout out the component with a size of 0x0

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top