简体   繁体   中英

GridBagLayout is not adding my panel

I am trying to add a three panels using GridBagLayout in JFrame . When the default layout is set, the panel is added without any problem, but when layout is changed to GridBagLayout and panel is added in JFrame , then the output is an empty frame.

Here is the code for MainFrame :

public class MainFrame extends JFrame {
    CirclePanel[] cp;

    MainFrame() throws IOException{
        cp = new CirclePanel[3];
        for(int i = 0 ;i <3 ; i ++)
            cp[i]= new CirclePanel(i+1);

        this.setSize(700, 700);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setLayout(new GridBagLayout());//when this line is not set then 
                                       //add(cp[0]) adds the panel
        GridBagConstraints gc = new GridBagConstraints();
        gc.weightx=1;
        gc.weighty=1;
        gc.gridx=0;
        gc.gridy=0;

        add(cp[1],gc);

        this.setVisible(true);
    }
}

I tried different step but was unable to add the panel using GridBagLayout or at least I was unable to show panel.

I want to add 3 consecutive panels with equal width by incrementing gc.gridx . The Main class contains only the main method, which is calling the MainFrame constructor.

In my custom panel class ( CirclePanel ) I used the paintComponent method to draw circles.

public class CirclePanel extends JPanel {

    private int mainCirclex ;//= getWidth()/2;
    private int mainCircley ;//= getHeight()/2;
    private final int mainCircler =1200;
    private final double ampRadius = 0.1;
//  private MakeArrays ma;
    private int[] firstCir;

    public CirclePanel(int num) throws IOException{
        firstCir = new int[175];
/*      ma = new MakeArrays();
        if(num == 1)
            firstCir = ma.getFirstCir();
        else if(num == 2)
            firstCir = ma.getSecondCir();
        else if(num == 3)
            firstCir = ma.getThirdCir();
        */
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
         Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(Color.BLACK);
            g2d.fillRect(getX(), getY(), getWidth(), getHeight());

            //////////main circle////////////////////
            //amplifying radius and setting x & y
            mainCircley = getHeight()/2;
            mainCirclex = getWidth()/2;
            int radius =  (int) (mainCircler*ampRadius);
            //drawing
            g2d.setColor(Color.yellow);
            g2d.drawOval(mainCirclex - radius, mainCircley - radius, 2 * radius, 2 * radius);
            /////////end main circle///////////

            //////////////sub circles//////////////
            int min = Math.min(mainCirclex, mainCircley);
            int r2 = Math.abs(min - radius) / 160;
            int j =0;
            for (int i = 0; i <360; i++) {

                if(j>=175) break;
                if(i%2==0){
                    double t = 2 * Math.PI * i / 360; 
                    int r = (int) (firstCir[j]*ampRadius);
                    //System.out.println(firstCir[j]);
                    int x = (int) Math.round(mainCirclex + r * Math.cos(t));
                    int y = (int) Math.round(mainCircley - r * Math.sin(t));
                    g2d.setColor(Color.red);
                    g2d.fillOval(x - r2, y - r2, 2 * r2, 2 * r2);
                    j++;
                }  
            }
        }
}

I added all 3 panels by incrementing the gridx value. To make it work I did the following:

  1. Added the line gc.fill = GridBagConstraints.BOTH to allow the panels to resize and fill extra space.

  2. Called setBackground in the panels' constructor instead of fillRect in paintComponent . It saves you the trouble of calculating the size of the panel.

  3. Overrode the getPreferredSize of the panels:

     @Override public Dimension getPreferredSize() { int size = (int) (2 * mainCircler * ampRadius); return new Dimension(size, size); } 

    (You might want to redo the calculation.)

  4. Called pack on the frame instead of setSize .

在此处输入图片说明

Explanation

The panels you are adding to the frame are empty from the layout manager's point of view - they don't have any child components. This means that panels will retain their default preferred is, which is 10x10 ( System.out.println(cp[1].getPreferredSize()) ) and they will be added to the frame with those dimensions.

Custom painting is not taken into account automatically when computing the preferred size of a component. If the preferred size is too small for the painting, it will not be displayed (or only part of it will). Overriding the getPreferedSize method of the panels to give the correct dimensions will tell the frame how to display them when pack is called.

Edit: comment answer

When I call setBackground to color the panels in their constructor it works fine, but when I try to use fillRect in paintComponent then the 1st panel is colored, but the next 2 panels aren't. Why is that?

Because of a very common misunderstanding (which is why I recommended point 2).

The getXXX() ( X , Y , Width , Height ) do not state the following explicitly, but they are derived from getBounds() , which reads:

Gets the bounds of this component in the form of a Rectangle object. The bounds specify this component's width, height, and location relative to its parent .

(emphasis mine.) So the bounds are in the parent's coordinate system . However, Graphics.fillRect paints with the given bounds in the component's coordinate system (the Graphics object passed to paintComponent is for painting the component, not its parent).

Then in order to paint the panel in its own coordinate system, we need

g2d.fillRect(0, 0, getWidth(), getHeight());

because a component always starts at (0,0) in its own coordinate system. Using

g2d.fillRect(getX(), getY(), getWidth(), getHeight());

takes the position of the panel in the parent and passes it to some non-special position in the panel. Moreover, if the panel is located in the parent's (300,300) , but the panel is less than (300,300) in size, then the drawing in the panel would in theory start outside of the panel . So, you see no painting.

The first panel paints because its (0,0) coincides with its parent's (0,0) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM