Chaps, I wonder if you can give me a hand with this. Here's the brief:
"Create a program that draws 10 random filled shapes in random colors, position and sizes. Method paintcomponent should contain a loop that iterates 10 times. In each iteration, the loop should determine whether to draw a filled rectangle or an oval, create a random color and choose coordinates and dimension at random. The coordinates should be chosen based on the panel's width and height. Lenghts of sides should be limited to half the width or height of the window. "
Right, so I managed to do that, code's here:

//ShapesTest.java
import javax.swing.JFrame;
public class ShapesTest{    
    public static void main( String[] args){

            Shapes panel = new Shapes();
            JFrame application = new JFrame();

            application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
            application.add( panel );
            application.setSize( 600, 600 );
            application.setVisible( true );
        }
    }

AND:

/*
p263 draw 10 random filled shapes in random colours, positions and sides
*/
//Shapes.java
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.Random;
public class Shapes extends JPanel{

    private static final Random randomShape = new Random(); 

    public void paintComponent( Graphics g ){
        super.paintComponent( g );
        int width = getWidth();
        int height = getHeight();
        int shape;//holding the shape
        int colour;//holding the colour
        int x;//holding x coordinate
        int y;//holding y coordinate
        int shapeWidth;
        int shapeHeight;

        for( int i = 0; i < 10; i++ ){
            //determine the coordinates and size of shapes to draw
            shape = decideShape();          
            colour = decideColour();

            x = decideCoordinates( width );
            y = decideCoordinates( height );

            shapeWidth = decideSize( width );
            shapeHeight = decideSize( height );

            //switch statement for colour
            switch( colour ){
                case 1:
                    g.setColor( Color.BLACK );
                    break;
                case 2:
                    g.setColor( Color.BLUE );
                    break;
                case 3:
                    g.setColor( Color.CYAN );
                    break;
                case 4:
                    g.setColor( Color.DARK_GRAY );
                    break;
                case 5:
                    g.setColor( Color.GRAY );
                    break;
                case 6:
                    g.setColor( Color.GREEN );
                    break;
                case 7:
                    g.setColor( Color.LIGHT_GRAY );
                    break;
                case 8:
                    g.setColor( Color.MAGENTA );
                    break;
                case 9:
                    g.setColor( Color.ORANGE );
                    break;
                case 10:
                    g.setColor( Color.PINK );
                    break;
                case 11:
                    g.setColor( Color.RED );
                    break;
                case 12:
                    g.setColor( Color.WHITE );
                    break;
                case 13:
                    g.setColor( Color.YELLOW );
                    break;
            }//colour switch

            //switch statement for shape
            switch( shape ){
                case 1:                     
                    g.fillOval( x, y, shapeWidth, shapeHeight );
                    break;              
                case 2:
                    g.fillRect( x, y, shapeWidth, shapeHeight );
                    break;
            }//shape switch         
        }//end of for loop                  
    }//end of paintComponent method

    //choose randomly the shape, 1 for oval, 2 for rectangle        
    public static int decideShape(){
        int theShape = 1 + randomShape.nextInt(2);
    //  System.out.printf("Shape value returned is %d\n", theShape);    
        return theShape;    
    }

    //choose randomly the colour among the 13 color objects
    public static int decideColour(){
        int theColour = 1 + randomShape.nextInt(13);//choose from the 13 predefined objects
        //System.out.printf("Colour value returned is %d\n", theColour);
        return theColour;
    }

    //choose random coordinates, x and y depending on the parameter passed to it
    public static int decideCoordinates( int origin ){
        int coordinate = randomShape.nextInt( origin + 1 );
        //System.out.printf("Coordinate value returned is %d\n", coordinate);
        return coordinate;
    }

    //choose random side lenghts
    public static int decideSize(int dimension){
        int side = randomShape.nextInt( dimension / 2 );
        //System.out.printf("Coordinate value returned is %d\n", side);
        return side;    
    }
}//end of class Shapes

So the problem I am having here is that after having run the program everytime I resize the java windows the shapes get drawn again, whereas I'd like them to stay as they are. Is that possible?

One more thing: the brief says to create a color, whereas I didn't really do that, but reused the color classes. Now, if I ought to create a colour, how would I go about it? I know there is this constructor Color(int r, int g, int b) but how could I use it in my program rather than reusing the 13 color classes?
any suggestion?
thanks

Recommended Answers

All 12 Replies

So you're using the method paintComponent(Graphics g) which paints whatever is within the JPanel. And everytime it repaints, it makes new shapes, because you used a random number gen.

If you want to make it so that it doesn't change, you need to somehow save what shapes were drawn which colors, or save the numbers that the random number returns.

In answer to your question about the color class, the constructor Color(int r, int g, int b) creates a new color with the specified values. So you would want something like this

//Random number gen 
Random rand = new Random();
//Color object
Color color = new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255));
//set Color of graphics object
g.setColor(color);

thanks...wouldn't have a clue how to save the shapes sorry : -). From memory the method paintComponent() is called implicitly, so this behaviour (whe you resize it is called) is normal isn't it?

Thanks for the code. So this Color color = new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)); calls an integer between 0 and 255?

  1. Yes. Swing calls paintComponent when needed. Resizing the container os one reason why a repaint would be needed.

  2. rand.nextInt(255) returns a random int in the range 0-254, not 255. The Color constructor takes three values 0-254 representing the red/green/blue components of the color, so that whole code creates a new color with random R G and B components covering the full range of valid colors.

ok thanks, so say something like this then:

//randomColours
//generates random colours
//Rgb.java
import java.util.Random;
import java.awt.Color;

public class Rgb{
        public static void main( String[] args){
            Random randomValue = new Random();
            for( int i=0; i < 10; i++ ){

                Color newColour = new Color(randomValue.nextInt(255), randomValue.nextInt(255), randomValue.nextInt(255));          
                System.out.println("New colour is " + newColour);
            }
        }   
    }

This should give me the int valies of colours? However the output is

New colour is java.awt.Color[r=171,g=55,b=174]
New colour is java.awt.Color[r=72,g=212,b=84]
New colour is java.awt.Color[r=181,g=21,b=162]
New colour is java.awt.Color[r=81,g=161,b=131]
New colour is java.awt.Color[r=120,g=2,b=143]
New colour is java.awt.Color[r=252,g=205,b=143]
New colour is java.awt.Color[r=127,g=117,b=145]
New colour is java.awt.Color[r=88,g=156,b=225]
New colour is java.awt.Color[r=92,g=192,b=46]
New colour is java.awt.Color[r=189,g=158,b=175]

How do I return just int numbers I can use somewhere else?
thanks

Actually to be correct, the Color constructor we're talking about takes 3 values in the range 0-255 (255 inclusive!)

Thus, to be entirely correct you'd need to call the constructor as follows:
new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256))

How do I return just int numbers I can use somewhere else?

You could use the getRed, getGreen and getBlue methods of the Color class and pass around Color objects.

So the problem I am having here is that after having run the program everytime I resize the java windows the shapes get drawn again, whereas I'd like them to stay as they are. Is that possible?
...
thanks...wouldn't have a clue how to save the shapes sorry : -)

Not required by the exercise, however, you can store your shapes in an ArrayList and in your paintComponent draw every shape in the list.

Yea, I'm sorry I forgot that it's not inclusive, I meant rand.nextInt(256)

You would want to return the entire color, not just the numerical value

//Color generating method
public Color genColor() {
    Random rand = new Random();
    Color col = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
    return col;
}

//painting code
g.setColor(genColor());


//Or if you want to generate just numbers for the color
public int genColorNum() {
    Random rand = new Random();
    return rand.nextInt(256);
}
//painting code
g.setColor(new Color(genColorNum(), genColorNum(), genColorNum());

Also I think it would be better if you had a global Random varible rather than using a temp one like I do. But it doesn't make much of a difference here.

uhm, I see thanks, but I can't quite understand how I could use it within the exercise. I could do something like this couldn' I?

/*
p263 draw 10 random filled shapes in random colours, positions and sides
*/
//Shapes.java
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.Random;
public class Shapes extends JPanel{

    private static final Random randomShape = new Random(); 

    public void paintComponent( Graphics g ){
        super.paintComponent( g );
        int width = getWidth();
        int height = getHeight();
        int shape;//holding the shape
        int colour;//holding the colour
        int x;//holding x coordinate
        int y;//holding y coordinate
        int shapeWidth;
        int shapeHeight;

        for( int i = 0; i < 10; i++ ){
            //determine the coordinates and size of shapes to draw
            shape = decideShape();          
            colour = decideColour();

            x = decideCoordinates( width );
            y = decideCoordinates( height );

            shapeWidth = decideSize( width );
            shapeHeight = decideSize( height );         

            //switch statement for shape
            switch( shape ){
                case 1:                     
                    g.fillOval( x, y, shapeWidth, shapeHeight );
                    break;              
                case 2:
                    g.fillRect( x, y, shapeWidth, shapeHeight );
                    break;
            }//shape switch         
        }//end of for loop                  
    }//end of paintComponent method

    //choose randomly the shape, 1 for oval, 2 for rectangle        
    public static int decideShape(){
        int theShape = 1 + randomShape.nextInt(2);
    //  System.out.printf("Shape value returned is %d\n", theShape);    
        return theShape;    
    }

** //choose randomly the colour
public static int decideColour(){
Color theColour = new Color(randomShape.nextInt(256), randomShape.nextInt(256), randomShape.nextInt(256));
//System.out.printf("Colour value returned is %d\n", theColour);
return theColour;
}**

    //choose random coordinates, x and y depending on the parameter passed to it
    public static int decideCoordinates( int origin ){
        int coordinate = randomShape.nextInt( origin + 1 );
        //System.out.printf("Coordinate value returned is %d\n", coordinate);
        return coordinate;
    }

    //choose random side lenghts
    public static int decideSize(int dimension){
        int side = randomShape.nextInt( dimension / 2 );
        //System.out.printf("Coordinate value returned is %d\n", side);
        return side;    
    }
}//end of class Shapes

but what type should be the variable int colour;//holding the colour if now holds a function that returns a Color type? SHOuld it be Color?
Then, should I call color.getRed, color.getGreen, color.getBlue to obtain the value?
thanks

Why not just return a Color, store the Color in a Color variable, use the Color, etc, as a Color object? Why do you want to use an int for this? Why do you want to get the RGB values, why not just use the Color in your g.setColor call?

ok sorry, I had another stab at it.
this is what I came back with. I have modified the code a little bit. The variavle colour is now of type Color because it calls a function of type Color (decideColour()) that returns a value of type color which is then the object that contains the red, green and red. Then this g.setColor(decideColour()); uses the colour values that will be emplyed when the shapes are drawn. It seems to work fine, let me know if it is correct(I haven't done arrays yet so I can't really use them):

/*
p263 draw 10 random filled shapes in random colours, positions and sides
*/
//Shapes.java
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.Random;
public class Shapes extends JPanel{

    private static final Random randomShape = new Random(); 

    public void paintComponent( Graphics g ){
        super.paintComponent( g );
        int width = getWidth();
        int height = getHeight();
        int shape;//holding the shape
        Color colour;//holding the colour
        int x;//holding x coordinate
        int y;//holding y coordinate
        int shapeWidth;
        int shapeHeight;

        for( int i = 0; i < 10; i++ ){
            //determine the coordinates and size of shapes to draw
            shape = decideShape();          
            colour = decideColour();


            x = decideCoordinates( width );
            y = decideCoordinates( height );

            shapeWidth = decideSize( width );
            shapeHeight = decideSize( height );

            g.setColor(decideColour());             

            //switch statement for shape
            switch( shape ){
                case 1:                     
                    g.fillOval( x, y, shapeWidth, shapeHeight );
                    break;              
                case 2:
                    g.fillRect( x, y, shapeWidth, shapeHeight );
                    break;
            }//shape switch         
        }//end of for loop                  
    }//end of paintComponent method

    //choose randomly the shape, 1 for oval, 2 for rectangle        
    public static int decideShape(){
        int theShape = 1 + randomShape.nextInt(2);
    //  System.out.printf("Shape value returned is %d\n", theShape);    
        return theShape;    
    }

    //choose randomly the colour 
    public static Color decideColour(){
        Color theColour = new Color(randomShape.nextInt(256), randomShape.nextInt(256), randomShape.nextInt(256));
        //System.out.printf("Colour value returned is %d\n", theColour);
        return theColour;
    }

    //choose random coordinates, x and y depending on the parameter passed to it
    public static int decideCoordinates( int origin ){
        int coordinate = randomShape.nextInt( origin + 1 );
        //System.out.printf("Coordinate value returned is %d\n", coordinate);
        return coordinate;
    }

    //choose random side lenghts
    public static int decideSize(int dimension){
        int side = randomShape.nextInt( dimension / 2 );
        //System.out.printf("Coordinate value returned is %d\n", side);
        return side;    
    }
}//end of class Shapes

thanks again

It looks correct to me. Except that you aren't using the varible colour (except on line 27 colour = decideColour();) But other than that, it looks just fine.

ah yes, I suppose I can get rid of it, you're right! thanks for your help!

Hi, I know it's very late to be replying to this, but I modified it to output both ovals and rectangles (Randomly) and colors in each shape (Randomly also)

package randomcolorsandshapes;
import javax.swing.*;
import java.awt.*;
import java.util.*;

public class ShapesNColor extends JPanel{

    private static final Random ranNum = new Random();
    public void paintComponent(Graphics g){
        super.paintComponent(g);

        int width = getWidth();
        int height = getHeight();
        int shape;      // Hold
//      int color;      // Hold
        int x;          // Hold
        int y;          // Hold
        int shapeWidth;
        int shapeHeight;

        for(int ktr = 0; ktr < 10; ktr++){
            Color ranCol = new Color(ranNum.nextInt(255), ranNum.nextInt(255), ranNum.nextInt(255));
            Color ranCol2 = new Color(ranNum.nextInt(255), ranNum.nextInt(255), ranNum.nextInt(255));

            //shape = decideShape();
//            color = decideColor();
            x = decideCoordinates(width);
            y = decideCoordinates(height);
            shapeWidth = decideSize(width);
            shapeHeight = decideSize(height);

            g.fillOval(x, y, shapeWidth, shapeHeight);
            g.setColor(ranCol);
            g.fillOval(x, y, shapeWidth, shapeHeight);
            g.fillRect(y, x, shapeHeight, shapeWidth);
            g.setColor(ranCol2);
            g.fillRect(x, y, shapeHeight, shapeWidth);

//            switch(shape){
//                case 1:
//                    g.fillOval(x, y, shapeWidth, shapeHeight);
//                    g.setColor(ranCol);
//                    g.fillOval(x, y, shapeWidth, shapeHeight);
//                case 2:
//                    g.fillRect(x, y, shapeWidth, shapeHeight);
//                    g.setColor(ranCol);
//                    g.fillRect(x, y, shapeWidth, shapeHeight);
//            }
        }

//        for(int ktr = 0; ktr < 10; ktr++){
//            switch(ranNum.nextInt(10)){
//                default:
//                case 1:
//                    g.drawOval(10, 20, 10, 20);
//                    g.setColor(ranCol);
//                    g.fillOval(ktr, ktr, ktr, ktr);
//                case 2:
//                    g.drawRect(ktr, ktr, ktr, ktr);
//                    g.setColor(ranCol);
//                    g.fillRect(ktr, ktr, ktr, ktr);
//                case 3:
//                    g.drawRoundRect(ktr, ktr, ktr, ktr, ktr, ktr);
//                    g.setColor(ranCol);
//                    g.fillRoundRect(ktr, ktr, ktr, ktr, ktr, ktr);
//            }
//        }
    }
//    public static int decideShape(){
//         int theShape = 1 + ranNum.nextInt(2);
//         return theShape;
//        }
//    public static int decideColor(){
//        int theColor = 1 + ranNum.nextInt(13);
//        return theColor;
//    }
    public static int decideCoordinates(int origin){
        int coordinate = ranNum.nextInt(origin + 1);
        return coordinate;
    }
    public static int decideSize(int dimension){
        int side = ranNum.nextInt(dimension / 2);
        return side;
    }
}

I comment out the unnecessary codes. :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.