如何在paintComponent中自动添加形状?

时间:2011-08-30 16:52:56

标签: java swing graphics acm-java-libraries

作为初学者,每当我想在框架内添加图形形状时,我都会这样做:

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

如何在画面内自动绘制无限数量的形状?如果我按照上面的方式操作,我只有有限数量的形状(Rect,Oval,没有别的)。

我正在寻找不同的东西,例如,每当方法addStuff(x, y)调用时,它会在坐标x和y处自动绘制“Stuff”,而无需再次手动编辑paintComponent内的任何内容

我曾经用acm包做过这件事,很容易。就像下面的代码一样。

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);
}

正如您在上面所看到的,我可以添加任意数量的圆圈,我知道它可以用页面来解释这个但我只是想要一个关于如何创建类似于上面代码的简短说明而不依赖于acm包

2 个答案:

答案 0 :(得分:2)

我会使用抽象类来定义此行为。

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);
    }
}

然后在你的绘画容器中你可以拥有

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);
}

然后在paintComponent(Graphics)内,你可以

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

答案 1 :(得分:1)

在您的课程JFrame中,添加一个私人会员,例如

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

和您的方法,例如

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

然后,在您的paintBackground方法中,有类似

的内容
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.
    }
}

作为初学者,这应该相当容易理解。一个更好的解决方案是使用MyShape方法获得自定义形状界面(即draw(Graphics g)),并从该界面(Circle implements MyShapeSquare implements MyShape等实现您的形状)。然后,您的ArrayList<Shape> shapes可能会变为ArrayList<MyShape> shapes,而您的paintBackground方法只会调用非常draw项的MyShape方法。