hi all, I need to draw a series (10) concentric circles starting fromt he middle of the panel. This is what I have done, do you reckon it is ok?

//Ovals.java

import java.awt.Graphics;
import javax.swing.JPanel;

public class Ovals extends JPanel{

    public void paintCmponent(Graphics g){
        super.paintComponent(g);
        //calculates the centre of the frame
        int widthMiddle = ((g.getWidth()) / 2);
        int heightMiddle = ((g.getHeight()) / 2);
        //draw the rectangles
        for(int = i; i < 10; i++){
            g.drawOval(widthMiddle - (i * 10), heightMiddle - (i * 10), 1 + (i * 10), 1 + (i * 10));
        }
    }


}

and

//OvalsTest.java
//This program draws concentric circles starting fromt the middle of the frame
import javax.swing.JFrame;
public OvalsTest{
    public void static main( String[], args){
        Ovals ovalsPanel = new Ovals();
        JFrame newFrame = new JFrame();

        newFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        newFrame.add( ovalsPanel );
        newFrame.setSize( 250, 250 );
        newFrame,setVisible( true );
    }
}

thanks

  • JPanel has implemented FlowLayout in API

  • FlowLayout accepting only PreferredSize that came from JComponents back to the container (JPanel in this case)

  • Painting in Swing, Graphics(2D) by default never returns any PreferredSize, have to override this Dimension

  • don't forget to set coordinates to the getHeight/Weight, instead of calculating this coordinates on the fly, and then painting will be resizable with contianer (JPanel)

  • I'd be put all Objects (Circles in your case) to the array, in all case, prepare these Objects before, including all required coordinates, then loop in array inside paintComponent only,

  • because paintComponent is called from all mouse and keys(if isFocusable()) events and internaly from methods implemented in API, when container or JComponent required for repaint() internally

Edited 3 Years Ago by mKorbel

thanks mKorbel for your suggestions, but I must say - sorry I haven't done so in my previous post - I am at the very beginning of my java career so to speak, so I haven't done arrays yet, I am still at chapter 5 of my Deitel and deitel book, so what you've said above sounds rather obscure to me...
I appreciate there are a million mor efficient ways to optimize the code I posted, but I'd rather keep it simple - and perhaps rather inefficient for the time being.
I know you mean well but:

JPanel has implemented FlowLayout in API

What do you mean?

FlowLayout accepting only PreferredSize that came from JComponents back to the container (JPanel in this case)

Not sure what it means sorry

Painting in Swing, Graphics(2D) by default never returns any PreferredSize, have to override this Dimension

really don't know

don't forget to set coordinates to the getHeight/Weight, instead of calculating this coordinates on the fly, and then painting will be resizable with contianer (JPanel)

Do you mean declare the two variables as private and set them with a setter method?

I'd be put all Objects (Circles in your case) to the array, in all case, prepare these Objects before, including all required coordinates, then loop in array inside paintComponent only,

I'd rather keep it simple, I appreciate that arrays are better but haven't got that far yet

because paintComponent is called from all mouse and keys(if isFocusable()) events and internaly from methods implemented in API, when container or JComponent required for repaint() internally

Really no idea what that means sorry

Your compiler will catch most of the problems that I see. Your compiler should be the first place you go for checking for problems because it is more reliable than human eyes at finding problems, and usually produces helpful and accurate explanations of the problems. I admit that sometimes it doesn't understand the nature of the mistake you made, but a little practice is all you need to figure out what really went wrong when it gives you a confusing message.

You are looking for the getWidth and getHeight methods of your JPanel, not your Graphics. Graphics doesn't have those methods.

If you want your circles to be concentric then they should get wider and taller twice as fast as they move left and up. Also, if the innermost circle has diameter one then it's not really a circle at all.

thanks for the feedback, sorry for making these silly mistakes! Here 's an improved version of it, I got the circles to work but for some reason the circles don't resize when I make the window bigger/smaller...how's that?

//Ovals.java

import java.awt.Graphics;
import javax.swing.JPanel;

public class Ovals extends JPanel{

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        //calculates the centre of the frame
        //int widthMiddle = ((getWidth()) / 2);
        //int heightMiddle = ((getHeight()) / 2);

        int width = getWidth();
        int height = getHeight();       
        System.out.printf("Width is %d \t and height is %d\n", width, height );

        //calculates the centre of the panel

        int xPoint = width / 2;
        int yPoint = height / 2;

        for(int i = 0; i < 10; i++){
            g.drawOval(xPoint - (i * 5), yPoint - (i * 5), (i * 10), (i * 10));
            //System.out.printf("Width is %d \t and height is %d\n", xPoint, yPoint );

        }

    }
}

and

//OvalsTest.java
//This program draws concentric circles starting fromt the middle of the frame
import javax.swing.JFrame;
public class OvalsTest{
    public static void main( String[] args){
        Ovals ovalsPanel = new Ovals();
        JFrame newFrame = new JFrame();

        newFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        newFrame.add( ovalsPanel );
        newFrame.setSize( 550, 550 );
        newFrame.setVisible( true );
    }
}

Any idea? thanks

for some reason the circles don't resize when I make the window bigger/smaller...how's that?

The circles don't resize because the circles are only exactly the size you told them to be, and never any other sizes. By the way, one of your circles now has a diameter of zero, so it's really not a circle at all, so you really have only 9 circles.

Your innermost circle has diameter 0, your next one has diameter 10, your next one has diameter 20, and so on all the way out. I would never have guessed that wasn't deliberate from the way it was written. If you want the circles to change size then you can use i * m instead of i * 5, and i * 2 * m instead of i * 10 and then make the value of m depend upon the size of the window some way that you feel looks right.

yep I know about the innermost circle, more like a dot really...I think I see what you mean now, and perhaps my terminology wasn't correct in that by resizing I actually meant draw more circles as you increase the sixe of the window and draw less as you decrease it.
So taking on board what you said, I suppose we are talking about something like this in the for loop:

for(int i = 0; i < xPoint / 10; i++){
            g.drawOval(xPoint - (i * 5), yPoint - (i * 5), (i * 10), (i * 10));
            //System.out.printf("Width is %d \t and height is %d\n", xPoint, yPoint );

        }

If you look at the previous code, xPoint is equal to width / 2. So if the width is about 550 (I say about because if I print the value of the width it is actually coming back with a value of 484px so I assument he rest is taken by the frame) then xPoint being 275 means that the loop will draw 27 circles. SO if the width increases the number of circles will increase too. The think is, I have chosen to divide xPoint by 10 only because the size of the circle increases of 10 pixels each time, but I kind of feel that the proportions are not quite ok somewhere, kinda missing something? Or do you reckon it is just about right?
thanks for your help

This article has been dead for over six months. Start a new discussion instead.