簡體   English   中英

GridBagLayout為列提供了額外的余量

[英]GridBagLayout gives extra margin to column

我已經和Swing一起工作了一段時間,終於找到了學習GridBadLayout的自信。

我仍在學習它,在這種情況下,我不明白為什么以下代碼沒有按預期方式響應:特別是我不明白為什么布局以這種方式顯示列。

通過運行摘要,您將發現代表意大利國旗的面板的位置不正確:最后一列(國旗的紅色部分)與國旗的其余部分(國旗的白色部分)分離。 那么,我在做錯什么,為了代表正確的標志,我可以解決什么問題?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class test extends JPanel {

    private GridBagConstraints gbc;
    private final int CELL_WIDTH = 90;
    private final int CELL_HEIGHT = 110;

    public test() {
        setLayout(new GridBagLayout());

        putBanner(0);

        putFlagRow(1);
        putFlagRow(2);
        putFlagRow(3);
        putFlagRow(4);
    }

    public JPanel getUserPanel(Color c) {
        JPanel ol = new JPanel();
        ol.setPreferredSize(new Dimension(CELL_WIDTH * 10, CELL_HEIGHT));
        ol.setBackground(c);
        return ol;
    }

    public JPanel gettestPanel() {
        JPanel ol = new JPanel();
        ol.setPreferredSize(new Dimension(CELL_WIDTH, CELL_HEIGHT));
        ol.setBackground(Color.white);
        return ol;
    }

    private void putFlagRow(int gridy) {
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = gridy;
        JPanel p1=gettestPanel();
        p1.setBackground(Color.green);
        add(p1, gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 3;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 4;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 5;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 6;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 7;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 8;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 9;
        gbc.gridy = gridy;
        JPanel p=gettestPanel();
        p.setBackground(Color.red);
        add(p, gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 10;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);
    }

    private void putBanner(int gridy) {
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = gridy;
        gbc.gridwidth = 1;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = gridy;
        gbc.gridwidth = 9;
        add(getUserPanel(Color.black), gbc);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("GridBagLayoutTest");
        frame.add(new test());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

除了了解此特定問題及其原因外,我還希望了解這一點,它直接來自GridBagLayout Oracle文檔:

weightx,weighty 指定權重是一門藝術,可能會對GridBagLayout控件的組件的外觀產生重大影響。 權重用於確定如何在列(權重)和行(權重)之間分配空間。 這對於指定調整大小的行為很重要。 除非您為weightx或weighty指定至少一個非零值,否則所有組件都將在其容器的中心聚集在一起。 這是因為當權重為0.0(默認值)時,GridBagLayout會在其單元格網格和容器邊緣之間放置任何多余的空間。 通常,權重的極限值設置為0.0和1.0:必要時使用中間的數字。 較大的數字表示組件的行或列應獲得更多的空間。 對於每一列,權重與該列中為組件指定的最高權重x有關,每個多列組件的權重均以某種方式在該組件所在的列之間分配。類似地,每一行的權重與為a所指定的最高權重有關。該行中的組件。 多余的空間傾向於流向最右邊的列和最下面的行。

像這樣的表達

是一門藝術

必要時使用中間的數字

確實給我的印象是,甚至文檔撰寫者都沒有想到可以教這種約束的用法。 那不好

weightX和weighty相當易於使用,但是本教程無濟於事...假設當您創建一個對話框並對其進行pack()時,組件將占據一個位置和大小,並且一切正常(或不正常)。 如果您調整對話框的大小並將其放大,會發生什么? 突然之間有更多的空間,組件也必須增加,這就是Swing查找weight*參數的時刻。

如果某個組件的weightx=1.0 ,其余weightx=0.0意味着第一個組件獲得所有新空間,第二個組件保持其大小。 如果組件的weightx=0.5表示這兩個組件共享新的大小,每個占50%。 如果組件的weightx值的總和大於1.0,則意味着組件需要的空間超過新空間的100%,所以...好吧,這很神奇...

假設您正在使用網絡瀏覽器。 您希望帶有選項卡,按鈕和菜單的頂部面板保持相同的尺寸,而網頁的中心面板獲得所有新的額外尺寸,因此您將中間面板的weight*=1.0weight*=0.0設為頂部面板。

嘗試在任何行或列中分配的權重不要超過1.0,一切都會好起來的。

最后一列(標志的紅色部分)與其余標志(標志的白色部分)分離。

調試GridBagLayout時,要做的一件事是向組件添加Border ,以便您可以看到每個單元格的大小。 我將以下內容添加到您的getTestPanel()方法中:

ol.setBorder( new LineBorder(Color.BLUE) );

您可以看到面板的尺寸正確,但是面板周圍有多余的空間。

然后,您查看用戶面板:

ol.setPreferredSize(new Dimension(CELL_WIDTH * 10, CELL_HEIGHT));

即使您僅將gridwidth設置為9個單元格,您也會看到大小設置為10個單元格。 因此,現在9個單元格必須適合用戶面板的空間,並且看起來這9列的最后一列有多余的空間。

代碼應為:

//ol.setPreferredSize(new Dimension(CELL_WIDTH * 10, CELL_HEIGHT));
ol.setPreferredSize(new Dimension(CELL_WIDTH * 9, CELL_HEIGHT));

另一個選擇是不為用戶面板提供首選的大小,而是使用“填充”約束,以便用戶面板現在將占用與九列相同的空間。

weightx,weighty指定重量是一門藝術...

這與您的問題無關。 若要查看此效果,請將框架拖動更大。 現在,由於您的組件都沒有使用weightx / weighty約束,因此整個面板都將放置在框架的中央。 這意味着如果使用框架,則所有組件都不會增長以填充空白空間。

如果組件之一的權重約束為1.0,則在調整框架大小時,該列將擴展並填充額外的空間。

我認為您想要達到的目標是這樣的:

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test extends JPanel {

    private static final long serialVersionUID = 1L;

    public Test() {
        setLayout(new GridBagLayout());
        putBanner(0);
        putFlagRow(1);
    }

    public JPanel getUserPanel(Color c) {
        JPanel panel = new JPanel();
        panel.setBackground(c);
        return panel;
    }

    private void putFlagRow(int gridy) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = gridy;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 0.5;
        gbc.weighty = 1;
        add(getUserPanel(Color.green), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = gridy;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1;
        gbc.weighty = 1;
        add(getUserPanel(Color.white), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = gridy;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 0.5;
        gbc.weighty = 1;
        add(getUserPanel(Color.red), gbc);
    }

    private void putBanner(int gridy) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = gridy;
        gbc.ipady = 50;
        gbc.fill = GridBagConstraints.BOTH;
        add(getUserPanel(Color.white), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = gridy;
        gbc.gridwidth = 2;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1;
        add(getUserPanel(Color.black), gbc);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("GridBagLayoutTest");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setContentPane(new Test());
        frame.setSize(450, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

GridBagLayout是對齊內容的一種非常復雜而強大的方法,用兩句話來解釋它並不是那么容易,所以我認為最簡單的方法是玩轉或觀看一些教程,但是我將嘗試:
您必須認為自己就像在編輯Excel表一樣。 如果您調整一個單元格的寬度,整個列的寬度將與行/高度相同。 因此,現在您不必添加白色飛機的色調,只需要一個並適當調整其大小即可。
接下來的事情不是設置固定的大小,布局將為您做到這一點,這就是它們的用途或使用絕對坐標(無布局: setLayout(null) )。
因此,現在您必須告訴GridBagLayout如何對齊組件。 不同的對齊方式有不同的變量。 首先(您應該已經知道), gridxgridy保持組件的位置(在Excel中類似A1或C12)。 比起您可以用gridwidthgridheight來“組合單元格”。
因此,現在您的組件已定位,但不會隨着窗口的大小而改變其大小。 直到知道該單元格只有其組件的getPreferredSize()的大小。 weightxweighty是接下來要查看的變量。 這些定義了應使用多少剩余空間。 例如,您有兩個組件(水平並排),它們的首選寬度總和為300px,但是窗口的寬度為1000px,則不會使用700px。 因此,如果現在將兩個weightx都設置為1,它們將嘗試使用100%的剩余像素,但它們不能同時具有700px,因此每個人都得到350px。 如果您現在將一個weightx設置為0,將另一個weightx設置為1,則第一個不會獲得額外的像素,而另一個全為700px。
如果您一直嘗試到現在,您將在面板之間看到很多空白,這是因為僅調整了單元格的大小,但未調整其內容。 現在,您可以設置要在組件中使用anchor顯示組件的位置(例如GridBagConstraints.NORTH / SOUTH / SOUTHEAST ),但是您仍然有這些空白,沒有標志有空白,您要找的是fill
fill讓您選擇如何處理單元格中的空白區域。 GridBagConstraints.NONE組件將不會被調整大小, HORIZONTAL僅調整大小寬度與單元格的寬度( VERTICAL僅高度)和BOTH調整大小以適合細胞大小的組件。
變量insets添加空的inset,例如,您選擇將fill設置為BOTH ,但是窗台想要在組件上方留有空白空間(inset是固定的,如果要動態inset,則必須通過在空白處添加空組件來解決。特定的GridBagConstraints來對齊要顯示的插圖)。
ipadxipady是要添加到單元格大小的固定值,例如ipadx設置為5,該單元格至少具有組件最小寬度的寬度加上ipadx的5px。 換句話說,單元格的寬度將始終至少比組件的寬度大5像素(如果將fill設置為BOTHHORIZONTAL ,組件隨后將被調整為新的寬度)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM