tags:

views:

376

answers:

2

Here's my code:

class Ramka extends JFrame
    {
    public static final int SZEROKOSC = 800;
    public static final int WYSOKOSC = 600;
    Container powZawartosci = getContentPane();
    public Ramka()
        {
        setSize(SZEROKOSC, WYSOKOSC);
        setTitle("Siatka bryły by Paweł Mysior");
        }
    public void addRectangle(int startX, int startY, int sizeX)
        {
        drawRectangle rect = new drawRectangle(startX, startY, sizeX);
        powZawartosci.add(rect);
        }  

class drawRectangle extends JPanel
    {
    private int a, startX, startY;
    public drawRectangle(int startX, int startY, int a) // square
        {
        this.a = a;
        this.startX = startX;
        this.startY = startY;
        }
    public void paintComponent(Graphics g)
        {
        Rectangle2D rect = new Rectangle2D.Double(startX, startY, a, a);
        Graphics2D g1 = (Graphics2D) g;
        g1.draw(rect);
        }
    }

public class Main
    {
    public static void main(String[] args)
        {
        Ramka ramka = new Ramka();
        ramka.addRectangle(200, 200, 50);
        ramka.addRectangle(100, 100, 100);
        ramka.addRectangle(300, 300, 150);
        ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ramka.setVisible(true);
        }
    }

What I want it to do is draw three rectangles (set aside the functionality and sense of doing so, I'm still just learning).

But it draws only the last one, starting at 300 and 300. I don't really understand the paintComponent thing...

Thanks in advance for any help, Paul

+1  A: 

I beleive that you are adding three JPanels on top of each other. This seems like an odd way to draw rectangles, but with this design, you need to use a LayoutManager.

Check out this link, and try to learn. The code below should do the trick though.

...
Container powZawartosci = getContentPane();
public Ramka()
    {
    setSize(SZEROKOSC, WYSOKOSC);
    setTitle("Siatka bryły by Paweł Mysior");
    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));//Only this line is inserted.
    }
public void addRectangle(int startX, int startY, int sizeX)
    {
    drawRectangle rect = new drawRectangle(startX, startY, sizeX);
    powZawartosci.add(rect);
    }  
...

In your JPanel derivative, you can keep track of the Rectangles that you need to draw. I am writing the code below spontanously, so check for errors first.

class RectangleDrawer extends JPanel{
    ArrayList<Rectangle> rList = new ArrayList()<Rectangle>;
    public void addRectangle(Rectangle rect){
        rList.add(rect);
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        for(int i=0; i<rList.size(); r++){
            g.drawRectangle(rList.get(i));
        }
    }
}
Erkan Haspulat
Right, lets say that I just want to draw those three rectangles, not necessarily with JPanel, what would you recommend then? Can I draw three rectangles in one JPanel?
PawelMysior
Yes, you can draw anything on one JPanel. I will be editing my post to explain better.
Erkan Haspulat
+1  A: 

The problem basically is that you're using two different levels of abstraction here.

In the first, you are adding a component to your JFrame, which is fine at some point.

You're adding your "DrawRectangle" instance, just the same way you would add a new button, a label or another panel. The problem comes when you add components in the same position. JFrame's main panel ( the content pane ) uses a "Border" layout manager that places the component in the middle if you don't add any constraint.

As a convenience, BorderLayout interprets the absence of a string specification the same as the constant CENTER

alt text

So, this line:

powZawartosci.add(rect);

Always adds your component in the "center", overriding the previous one. That's why you only saw one rectangle.

The second level of abstraction used here is painting the component yourself. This is low level and you have to tell the component who to draw each line and where.

That's fine, but if you want to draw several rectangles in the same component, you have to hold the references for each one ( using a collection like a list ) and then iterate that collection and draw them all.

Like this:

many

I took your code, and changed it, to reflect what I'm saying. The final result, uses the same component, but this component in turn draws all the rectangles.

Notice also the naming/brace style, while is not mandatory it is common while programming in Java

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

class Ramka extends JFrame {
    public static final int SZEROKOSC = 800;
    public static final int WYSOKOSC = 600;
    Container powZawartosci = getContentPane();
    DrawRectangle rectangle = new DrawRectangle();
    public Ramka() {
        setSize(SZEROKOSC, WYSOKOSC);
        setTitle("Siatka bryły by Paweł Mysior");
        powZawartosci.add( new JLabel("Several rectangles are being displayed"), BorderLayout.NORTH );
        powZawartosci.add(rectangle);
    }
    public void addRectangle(int startX, int startY, int sizeX) {
        this.rectangle.addRectangle( startY, startY, sizeX );
    }

}  

class DrawRectangle extends JPanel {
    private java.util.List<Rectangle2D> squares;
    //private int a, startX, startY;
    public DrawRectangle(){
        squares = new ArrayList<Rectangle2D>();
    }

    public void addRectangle(int startX, int startY, int a)  { // square
        squares.add( new Rectangle2D.Double(startX, startY, a, a) ) ;
        //this.a = a;
        //this.startX = startX;
        //this.startY = startY;
    }
    public void paintComponent(Graphics g) {
        Graphics2D g1 = (Graphics2D) g;
        for( Rectangle2D rect : squares ) {
            g1.draw(rect);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Ramka ramka = new Ramka();
        //ramka.addRectangle(200, 200, 50);
        //ramka.addRectangle(100, 100, 100);
        //ramka.addRectangle(300, 300, 150);
        for( int i = 0 ; i < 20 ; i++ ){
            ramka.addRectangle( i * 10 , i * 10 , i * 20 );
        } 
        ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ramka.setVisible(true);
    }
}
OscarRyz
Thanks, I guess I know understand what I was doing wrong. Thanks once again ;]
PawelMysior