GridBagLayout没有添加我的面板

时间:2022-12-15 00:06:48

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.

我想在JFrame中使用GridBagLayout添加三个面板。设置默认布局时,添加面板没有任何问题,但是当布局更改为GridBagLayout并且面板添加到JFrame中时,则输出为空框架。

Here is the code for MainFrame:

以下是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.

我尝试了不同的步骤,但无法使用GridBagLayout添加面板,或者至少我无法显示面板。

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.

我想通过递增gc.gridx来添加3个具有相等宽度的连续面板。 Main类只包含main方法,它调用MainFrame构造函数。

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

在我的自定义面板类(CirclePanel)中,我使用paintComponent方法绘制圆。

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

1 个解决方案

#1


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

我通过递增gridx值添加了所有3个面板。为了使它工作,我做了以下:

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

    添加了行gc.fill = GridBagConstraints.BOTH以允许面板调整大小并填充额外空间。

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

    在面板的构造函数中调用setBackground而不是paintComponent中的fillRect。它可以省去计算面板尺寸的麻烦。

  3. Overrode the getPreferredSize of the panels:

    覆盖面板的getPreferredSize:

    @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.

    在框架上调用包而不是setSize。

GridBagLayout没有添加我的面板

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.

从布局管理器的角度来看,添加到框架的面板是空的 - 它们没有任何子组件。这意味着面板将保留其默认首选值,即10x10(System.out.println(cp [1] .getPreferredSize())),它们将添加到具有这些尺寸的框架中。

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.

在计算组件的首选大小时,不会自动考虑自定义绘画。如果首选尺寸对于绘画而言太小,则不会显示(或仅显示其中的一部分)。覆盖面板的getPreferedSize方法以提供正确的尺寸将告诉框架在调用pack时如何显示它们。

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?

当我调用setBackground为它们的构造函数中的面板着色时,它工作正常,但是当我尝试在paintComponent中使用fillRect时,第一个面板是彩色的,但接下来的两个面板不是。这是为什么?

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

由于一个非常普遍的误解(这就是我推荐第2点的原因)。

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

getXXX()(X,Y,Width,Height)没有明确说明以下内容,但是它们是从getBounds()派生的,它读取:

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.

以Rectangle对象的形式获取此组件的边界。边界指定此组件相对于其父组件的宽度,高度和位置。

(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).

(强调我的。)因此边界在父母的坐标系中。但是,Graphics.fillRect使用组件坐标系中的给定边界进行绘制(传递给paintComponent的Graphics对象用于绘制组件,而不是其父组件)。

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

因为组件始终在其自己的坐标系中从(0,0)开始。运用

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.

获取父级中面板的位置,并将其传递到面板中的某个非特殊位置。此外,如果面板位于父母(300,300)中,但面板尺寸小于(300,300),那么面板中的绘图理论上将从面板外部开始。所以,你看不到画。

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

第一个面板绘制,因为它的(0,0)与其父级(0,0)重合。

#1


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

我通过递增gridx值添加了所有3个面板。为了使它工作,我做了以下:

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

    添加了行gc.fill = GridBagConstraints.BOTH以允许面板调整大小并填充额外空间。

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

    在面板的构造函数中调用setBackground而不是paintComponent中的fillRect。它可以省去计算面板尺寸的麻烦。

  3. Overrode the getPreferredSize of the panels:

    覆盖面板的getPreferredSize:

    @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.

    在框架上调用包而不是setSize。

GridBagLayout没有添加我的面板

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.

从布局管理器的角度来看,添加到框架的面板是空的 - 它们没有任何子组件。这意味着面板将保留其默认首选值,即10x10(System.out.println(cp [1] .getPreferredSize())),它们将添加到具有这些尺寸的框架中。

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.

在计算组件的首选大小时,不会自动考虑自定义绘画。如果首选尺寸对于绘画而言太小,则不会显示(或仅显示其中的一部分)。覆盖面板的getPreferedSize方法以提供正确的尺寸将告诉框架在调用pack时如何显示它们。

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?

当我调用setBackground为它们的构造函数中的面板着色时,它工作正常,但是当我尝试在paintComponent中使用fillRect时,第一个面板是彩色的,但接下来的两个面板不是。这是为什么?

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

由于一个非常普遍的误解(这就是我推荐第2点的原因)。

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

getXXX()(X,Y,Width,Height)没有明确说明以下内容,但是它们是从getBounds()派生的,它读取:

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.

以Rectangle对象的形式获取此组件的边界。边界指定此组件相对于其父组件的宽度,高度和位置。

(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).

(强调我的。)因此边界在父母的坐标系中。但是,Graphics.fillRect使用组件坐标系中的给定边界进行绘制(传递给paintComponent的Graphics对象用于绘制组件,而不是其父组件)。

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

因为组件始终在其自己的坐标系中从(0,0)开始。运用

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.

获取父级中面板的位置,并将其传递到面板中的某个非特殊位置。此外,如果面板位于父母(300,300)中,但面板尺寸小于(300,300),那么面板中的绘图理论上将从面板外部开始。所以,你看不到画。

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

第一个面板绘制,因为它的(0,0)与其父级(0,0)重合。