2

I have the code

import java.awt.*;
import javax.swing.*;

public class MondrianPanel extends JPanel
{
    public MondrianPanel()
    {
        setPreferredSize(new Dimension(200, 600));
    }

    public void paintComponent(Graphics g) {
        for(int i = 0; i < 20; i++) {
            paint(g);
        }
    }

    public void paint(Graphics g)
    {
        Color c = new Color((int)Math.random()*255, (int)Math.random()*255, (int)Math.random()*255);
        g.setColor(c);
        g.fillRect((int)Math.random()*200, (int)Math.random()*600, (int)Math.random()*40, (int)Math.random()*40);
    }

}

What I'm trying to get it to do is draw a bunch of randomly colored rectangles at random places on the screen. However, when I run it, I just get a gray box. I was reading this question Drawing multiple lines with Java Swing and I saw that you should have a single paintComponent that calls paint a bunch of times and I tried adapting my code to this, but it still doesn't work.

Community
  • 1
  • 1
Austin Gayler
  • 4,038
  • 8
  • 37
  • 60
  • PaintComponent will never be called, as it is normally called from paint. It is preferred practice to override paintComponent of Swing components instead of paint, partly because its double buffered and partly because here are multiple layers of painting occurring in the system. Take a look at [Painting in AWT and Swing](http://www.oracle.com/technetwork/java/painting-140037.html) for more information – MadProgrammer Jan 15 '13 at 20:21
  • possible duplicate of [Strange JFrame Behavior](http://stackoverflow.com/questions/13822019/strange-jframe-behavior) – David Kroukamp Jan 16 '13 at 13:59

1 Answers1

4

The biggest problem here is that the (int) Math.random() * something is always 0. That's because the cast is executed first and is 0 and then multiplied by something is still 0.

It should be something like this: (int) (Math.random() * something).

Then, you should rename paint(Graphics g) to draw(Graphics g), otherwise you are overwriting paint in a wrong way.

The code below is working as you need:

public class TestPanel extends JPanel {
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i = 0; i < 20; i++) {
            draw(g);
        }
    }

    public void draw(Graphics g) {
        Color c = new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255));
        g.setColor(c);
        g.fillRect((int) (Math.random() * 400), (int) (Math.random() * 300), (int) (Math.random() * 40), (int) (Math.random() * 40));
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.getContentPane().add(new TestPanel(), BorderLayout.CENTER);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(400, 300);
        f.setVisible(true);
    }
}
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
Dan D.
  • 32,246
  • 5
  • 63
  • 79
  • 1
    @dan It would nice if you could demonstrate calling super.paintComponent in order to maintain the proper paint chain etiquette, other wise, nice example – MadProgrammer Jan 15 '13 at 20:22
  • 1) Not too sure about that `Math.random()` see [here](http://stackoverflow.com/questions/738629/math-random-versus-random-nextintint) for reasoning. 2) `setSize(..)` is a no no rather use an appropriate `LayoutManager` and/or override `getPreferredSize()` of `JPanel` than call `pack()` on `JFrame` 3) Also please create Swing components on EDT. – David Kroukamp Jan 16 '13 at 13:58