Question

As a beginner, whenever I want to add graphical shapes inside the frame I do something like this:

public void paintComponent(Graphics g) {
    super.paintComponent(g); 
    g.fillRect(0, 0, 10, 10);
    g.fillOval(10,10,10,10);
}

How do I draw an unlimited number of shapes automatically inside the frame? If I follow the way I did above I only have a limited number of shapes(Rect, Oval and nothing else).

I'm looking for something different, for example, whenever a method addStuff(x, y) has called, it draws "Stuff" automatically at the coordinate x and y without having to edit anything inside paintComponent manually again.

I used to do this with the acm package and it was easy. Just like the code below.

for (int i = 0; i < NCIRCLES; i++) {
    double r = rgen.nextDouble(MIN_RADIUS, MAX_RADIUS);
    double x = rgen.nextDouble(0, getWidth() - 2 * r);
    double y = rgen.nextDouble(0, getHeight() - 2 * r);
    GOval circle = new GOval(x, y, 2 * r, 2 * r);
    circle.setFilled(true);
    circle.setColor(rgen.nextColor());
    add(circle);
}

As you can see above, I can add as many circles as I want, I know it can take pages to explain this but I just want a brief instruction on how to create something similar to the code above without relying on acm package.

Was it helpful?

Solution

I would use an abstract class to define this behavior.

abstract class OpalDraw {
    protected int x1, y1, x2, y2;
    protected OpalDraw(int x1, int y1, int x2, int y2) {
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
    }
    abstract public void draw(Graphics g);
}

class OpalOval {
    public OpalOval(int x1, int y1, int x2, int y2) { super(x1,y1,x2,y1); }
    public void draw(Graphics g) {
        g.drawOval(x1,y1,x2,y1);
    }
}

class OpalRect {
    public OpalRect(int x1, int y1, int x2, int y2) { super(x1,y1,x2,y1); }
    public void draw(Graphics g) {
        g.drawRect(x1,y1,x2,y1);
    }
}

Then in your painting container you can have

addOval(int x1, int y1, int x2, int y2) {
    myDraws.add(new OpalOval(x1,x2,y1,y2);
}

addRect(int x1, int y1, int x2, int y2) {
    myDraws.add(new OpalRect(x1,x2,y1,y2);
}

Then later inside paintComponent(Graphics) you can

for(OpalDraw draw : myDraws) draw.draw(g);

OTHER TIPS

In your class extending JFrame, add a private member like

private ArrayList<Shape> shapes = new ArrayList<Shape>();

and your methods, for example

public void addRectangle(int x, int y, int with, int height) {
    shapes.add(new Rectangle(x, y, width, height));
}

Then, in your paintBackground method, have something like

public void paintComponent(Graphics g) {
    super.paintComponent(g); 

    for (Shape shape : shapes) {
        if (shape instanceof Rectangle2D) {
            g.drawRect(shape.getX(), shape.getY(), shape.getWidth(), shape.getHeight());

        } else if (shape instanceof Ellipse2D) {
            // ...
        } // else if ...
            // etc.
    }
}

As a beginner, this should be fairly easy to understand. A yet better solution would be to have custom shape interface (ie. MyShape) with a draw(Graphics g) method, and implement your shapes from that interface (Circle implements MyShape, Square implements MyShape, etc.). Then, your ArrayList<Shape> shapes could become ArrayList<MyShape> shapes and your paintBackground method would just invoke the draw method of very MyShape items.

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