GridBagLayout使用

原文鏈接:https://www.jianshu.com/p/b0f781c3e8c2

衆所周知,GridBagLayout是swing提供的一種十分靈活的佈局方式,正因其靈活性,所以每次用java做GUI程序時,我都會首選這種佈局方式,但是每次用,感覺像扔色子猜點數,歸其原因,主要是未理解GridBagLayout的設計理念,自然對其衆多參數對佈局的影響理解模棱兩可,在做時只好去猜測各個參數含義,不斷的嘗試。這次做自己的一個小的java程序,在反覆嘗試下,終於明白了GridBagLayout的設計理念,如有錯誤之處,請多多指教。

概述

個人認爲GridBagLayout設計理念是將父容器看作一個表格,表格中單元格的長寬可根據需求調整,可調整是指如下圖1所示,通過豎線和橫線的位置,來調整單元格大小,而不是如圖2所示那樣,任意的設置單元格大小,組件可以放在一個或多個連續的單元格中,且這些連續單元格最後所構成的區域必須是一個方形區域,下面我會以方格來代指這個方形區域。

示意圖

 

據我所知,GridBagLayout不能夠指定行數和列數,行數和列數是由swing根據父容器中各個組件設置的相關參數,自動計算出來的。如果讀者發現可以明確指定行數和列數,請指教。

GridBagLayout參數

一個組件在父容器中的位置,由其設置的GridBagLayout的參數決定,而GridBagLayout參數封裝在GridBagConstraints類中,其主要成員變量如下:

與組件所在方格相關的參數

變量名 作用
gridx 方格左上角單元格所在行號,行號在表格中以0開始,從左到右依次編號
gridy 方格左上角單元格所在列號,列號在表格中以0開始,從上到下依次編號
gridwidth 方格在橫向佔用的單元格數
gridheight 方格在縱向佔用的單元格數
weightx 方格的長與表格長(即父容器的長)的比例,若爲0,則爲組件默認長度
weighty 方格的寬與表格寬(即父容器的寬)的比例,若爲0,則爲組件默認寬度

如下圖所示,父容器被分割成3*3的表格,各行各列佔比如圖中小數所示,然後在該容器中分別放了方格1,方格2,方格3,以方格3爲例,其gridx=0,gridy=2,gridwidth=2,gridheight=1,weightx=0.2,weighty=0.5。

示意圖

效果圖

代碼如下:

package test.swing;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

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

public class GridWeightTest {
    
    public static void main(String[] args) {
        JFrame frame = new JFrame("GridWeightTest");
        frame.setLocation(10, 10);
        frame.setSize(600, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        JPanel centerPane = new JPanel();
        
        frame.add(centerPane, BorderLayout.CENTER);
        
        centerPane.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.BOTH;
        
        JButton btn1 = new JButton("方格1");
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.gridheight = 2;
        gbc.weightx = 0.5;
        gbc.weighty = 0.8;
        centerPane.add(btn1, gbc);
        
        JButton btn2 = new JButton("方格2");
        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.gridheight = 3;
        gbc.weightx = 0.5;
        gbc.weighty = 1;
        centerPane.add(btn2, gbc);
        
        JButton btn3 = new JButton("方格3");
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        gbc.gridheight = 1;
        gbc.weightx = 0.5;
        gbc.weighty = 0.2;
        centerPane.add(btn3, gbc);
        
        frame.setVisible(true);
    }
}

注:對於上面的參數個人理解不是十分充分,對於下圖這種情況,方格1與方格3沒有一條邊是水平對齊的,我還沒找出相應的參數設置方案,讀者若有相應的參數設置方案,請指教。此外,讀者若感興趣,可以寫代碼測試下若行或者列上的所有weightx或weighty和不爲1,swing會如何顯示?

示意圖

組件放置在方格中,即組件只能在其所在方格中顯示,若組件比所在方格大,則只會顯示組件的一部分,下面是與組件在方格中的位置,組件大小相關的參數:

變量名 作用
fill 但當組件比方格小時,組件如何填充方格中剩餘空間,有水平填充(HORIZONTAL),垂直填充(VERTICAL)等方式,詳細請看GridBagConstraints API
anchor 當組件比方格小時,組件在方格中的位置,可以是方格北方(WEST),方格南方(SOUTH),東方(EAST)等位置,詳細請看GridBagConstraints API
JComponent.setPreferredSize 設置組件對象的大小,繼承自JComponent的組件均可使用該方法,之所以在這兒加一個與GridBagLayout不相關的方法,是因爲有時組件對象的默認大小不合適,而使用fill填充,也感覺不合適,那就只好由自己設置組件大小了

以實現下圖效果爲例。

示意圖

 

效果圖

代碼如下:

package test.swing;

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

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

public class FillTest {
    
    public static void main(String[] args) {
        JFrame frame = new JFrame("FillTest");
        frame.setLocation(10, 10);
        frame.setSize(600, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        JPanel centerPane = new JPanel();
        
        frame.add(centerPane, BorderLayout.CENTER);
        
        centerPane.setLayout(new GridBagLayout());
        centerPane.setBackground(Color.CYAN);
        GridBagConstraints gbc = new GridBagConstraints();
        
        JButton btn1 = new JButton("組件");
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        gbc.gridheight = 2;
        gbc.weightx = 0.5;
        gbc.weighty = 0.8;
        gbc.fill = GridBagConstraints.NONE;
        gbc.anchor = GridBagConstraints.NORTHWEST;
        centerPane.add(btn1, gbc);
        
        JButton btn2 = new JButton("組件");
        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.gridheight = 3;
        gbc.weightx = 0.5;
        gbc.weighty = 1;
        gbc.fill = GridBagConstraints.NONE;
        gbc.anchor = GridBagConstraints.CENTER;
        centerPane.add(btn2, gbc);
        
        JButton btn3 = new JButton("組件");
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        gbc.gridheight = 1;
        gbc.weightx = 0.5;
        gbc.weighty = 0.2;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.SOUTH;
        centerPane.add(btn3, gbc);
        
        frame.setVisible(true);
    }
}

其他參數

下面兩個參數比較好理解,讀者若感興趣,不妨自己寫代碼測試,瞭解其作用。

變量名 作用
ipadx 自行測試
ipady 自行測試
insets 自行測試

swing零散技巧

  • 在父容器中添加許多組件後,如何讓父容器出現滾動條?如何設置滾動條滾動速度?

JScrollPane sPane = new JScrollPane(centerPanel),設置滾動條垂直(豎向類似)速度sPane.getVerticalScrollBar().setUnitIncrement(要設置的速度);

  • 刪除父容器中的組件後,但是父容器沒有變化,如何可以立即刷新父容器?

不妨試着調用父容器或者父容器的validate()或者doLayout()或者repaint()方法



作者:牆角的蟈蟈
鏈接:https://www.jianshu.com/p/b0f781c3e8c2
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章