【從零開始學 Java 程式設計】 進階佈局管理器 - GridBagLayout
【從零開始學 Java 程式設計】 線上教學課程目錄,使用 Java 程式語言,開發應用程式。
GridBagLayout
GridBagLayout 網格群佈局,透過元件加入容器時使用 GridBagConstraints 設定相關參數來進行佈局。共有以下這些參數進行設定:
gridx, gridy
用來指定元件將擺放在網格中的哪一行和哪一列當中。最左上角第一格為 gridx = 0, gridy = 0。
- 元件A
gridx = 0
gridy = 0 - 元件B
gridx = 3
gridy = 2 - 元件C
gridx = 4
gridy = 5
gridwidth, gridheight
用來指定元件顯示區域所佔的列數和行數,以網格為單位而不是像素為單位,預設值值為 1,佔用一個網格。
- 元件A
gridx = 0
gridy = 0
gridwidth = 1
gridheight = 1 - 元件B
gridx = 3
gridy = 2
gridwidth = 2
gridheight = 1 - 元件C
gridx = 4
gridy = 4
gridwidth = 2
gridheight = 2
fill
用來指定元件填充網格的方式。
GridBagConstraints.NONE(預設值)
GridBagConstraints.HORIZONTAL (以水平填充其顯示區域)
GridBagConstraints.VERTICAL (以垂直填充其顯示區域)
GridBagConstraints.BOTH (完全填充其顯示區域)
GridBagConstraints.HORIZONTAL (以水平填充其顯示區域)
GridBagConstraints.VERTICAL (以垂直填充其顯示區域)
GridBagConstraints.BOTH (完全填充其顯示區域)
- 元件A
gridx = 0
gridy = 0
gridwidth = 2
gridheight = 2
fill = GridBagConstraints.NONE - 元件B
gridx = 3
gridy = 2
gridwidth = 2
gridheight = 2
fill = GridBagConstraints.HORIZONTAL - 元件C
gridx = 4
gridy = 4
gridwidth = 2
gridheight = 2
fill = GridBagConstraints.VERTICAL - 元件D
gridx = 4
gridy = 4
gridwidth = 2
gridheight = 2
fill = GridBagConstraints.BOTH
ipadx, ipady
用來指定元件顯示區域的內部填充,即在元件最小尺寸之外需要附加的像素值,預設值為0。
拉大元件大小 ipadx、ipady 為正值,如:10
縮小元件大小 ipadx、ipady 為負值,如:-10
insets
用來指定元件的外部填充,即元件與其顯示區域邊緣之間的間距(元件上下左右間距)。
anchor
用來指定元件在顯示區域中的擺放位置。
- 絕對值
GridBagConstraints.NORTH
GridBagConstraints.SOUTH
GridBagConstraints.WEST
GridBagConstraints.EAST
GridBagConstraints.NORTHWEST
GridBagConstraints.NORTHEAST
GridBagConstraints.SOUTHWEST
GridBagConstraints.SOUTHEAST
GridBagConstraints.CENTER (預設) - 方向相對值
GridBagConstraints.PAGE_START
GridBagConstraints.PAGE_END
GridBagConstraints.LINE_START
GridBagConstraints.LINE_END
GridBagConstraints.FIRST_LINE_START
GridBagConstraints.FIRST_LINE_END
GridBagConstraints.LAST_LINE_START
GridBagConstraints.LAST_LINE_END - 基線相對值
GridBagConstraints.BASELINE
GridBagConstraints.BASELINE_LEADING
GridBagConstraints.BASELINE_TRAILING
GridBagConstraints.ABOVE_BASELINE
GridBagConstraints.ABOVE_BASELINE_LEADING
GridBagConstraints.ABOVE_BASELINE_TRAILING
GridBagConstraints.BELOW_BASELINE
GridBagConstraints.BELOW_BASELINE_LEADING
GridBagConstraints.BELOW_BASELINE_TRAILIN
weightx, weighty
用來指定在容器大小改變時,增加或減少元件中的的空間分配。weightx (行)和weighty(列)的值一般在0.0與1.0之間,預設值為0,數值越大代表組件所在的行或者列將獲得更多的空間。
預設值為0,視窗拉大、縮小都不變化元件大小
設定 weightx, weighty 將會根據比例變化大小
範例一
練習透過 gridx 和 gridy 指定按鈕位置
public void addComponentsToPane(Container pane) {
//宣告 GridBagLayout
GridBagLayout gridBagLayout = new GridBagLayout();
//設定佈局方式為 GridBagLayout
pane.setLayout(gridBagLayout);
//宣告網格約束變數
GridBagConstraints c;
//宣告按鈕變數
JButton btn;
//新增一個按鈕,並設定網格約束
btn = new JButton("btn1");
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
pane.add(btn, c);
//新增一個按鈕,並設定網格約束
btn = new JButton("btn2");
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 1;
c.gridy = 1;
pane.add(btn, c);
//新增一個按鈕,並設定網格約束
btn = new JButton("btn3");
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 2;
c.gridy = 2;
pane.add(btn, c);
}
範例二
承上面範例,修改 gridwidth,讓 btn3 佔滿三格網格。
注意的是,除了 gridwidth=3 外,還要搭配 gridx 和 gridy 修改,否則無法佔滿三格。
btn = new JButton("btn3");
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 3; //佔用三格,需要 gridx 和 gridy 搭配
c.gridx = 0;
c.gridy = 2;
pane.add(btn, c);
範例三
承上面範例,修改 ipady ,讓 btn2 長高變大顆長按鈕。(如果是調整 ipadx,則會讓按鈕長胖左右變大)。
btn = new JButton("btn2");
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 100; //長高變長按鈕
//c.ipadx = 100;
c.gridx = 1;
c.gridy = 1;
pane.add(btn, c);
範例四
承上面範例,修改 insets ,讓 btn3 ,與上面元件間距拉大。
btn = new JButton("btn3");
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 3;
c.insets = new Insets(100,0,0,0);//調整間距
c.gridx = 2;
c.gridy = 2;
pane.add(btn, c);
範例五
預設為GridBagConstraints.RELATIVE 情況下,元件會一個接一個使用排序下去,練習透過 REMAINDER 結束一行來佈局,新增的元件在將在下一行接續下去。
public void makeButton(Container pane, String title, GridBagLayout gridBagLayout, GridBagConstraints constraints) {
JButton button = new JButton(title); //創建Button對象
gridBagLayout.setConstraints(button, constraints);
pane.add(button);
}
public void addComponentsToPane(Container pane) {
//宣告 GridBagLayout
GridBagLayout gridBagLayout = new GridBagLayout();
//設定佈局方式為 GridBagLayout
pane.setLayout(gridBagLayout);
//宣告網格約束變數
GridBagConstraints c;
JTextField jTextField = new JTextField();
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 10;
c.gridwidth = GridBagConstraints.REMAINDER;//第一列,結束行
pane.add(jTextField, c);
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 50;
makeButton(pane, "btn1", gridBagLayout, c);
makeButton(pane, "btn2", gridBagLayout, c);
c.gridwidth = GridBagConstraints.REMAINDER;//第二列,結束行
makeButton(pane, "btn3", gridBagLayout, c);
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 50;
makeButton(pane, "btn4", gridBagLayout, c);
makeButton(pane, "btn5", gridBagLayout, c);
c.gridwidth = GridBagConstraints.REMAINDER;//第三列,結束行
makeButton(pane, "btn6", gridBagLayout, c);
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 50;
makeButton(pane, "btn7", gridBagLayout, c);
makeButton(pane, "btn8", gridBagLayout, c);
c.gridwidth = GridBagConstraints.REMAINDER;//第四列,結束行
makeButton(pane, "btn9", gridBagLayout, c);
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 50;
makeButton(pane, "btn10", gridBagLayout, c);
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 2;
c.ipady = 50;
makeButton(pane, "btn11", gridBagLayout, c);
c.gridwidth = GridBagConstraints.REMAINDER;//第五列,結束行
}
補充資料
12306訂票助手,即是採用 GridBagLayout 來完成如下方畫面,完整詳細程式碼,可以參考: github 源始碼
部分佈局程式碼
setExtendedState(JFrame.MAXIMIZED_BOTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 1051, 781);
m_contentPane = new JPanel();
setContentPane(m_contentPane);
GridBagLayout gbl_m_contentPane = new GridBagLayout();
gbl_m_contentPane.columnWidths = new int[] { 1024, 0 };
gbl_m_contentPane.rowHeights = new int[] { 50, 150, 126, 39, 148, 0 };
gbl_m_contentPane.columnWeights = new double[] { 1.0, Double.MIN_VALUE };
gbl_m_contentPane.rowWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 1.0, Double.MIN_VALUE };
m_contentPane.setLayout(gbl_m_contentPane);
panel_4 = new JPanel();
GridBagConstraints gbc_panel_4 = new GridBagConstraints();
gbc_panel_4.fill = GridBagConstraints.BOTH;
gbc_panel_4.insets = new Insets(0, 0, 5, 0);
gbc_panel_4.gridx = 0;
gbc_panel_4.gridy = 0;
m_contentPane.add(panel_4, gbc_panel_4);
panel_4.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"),
"\u7B2C\u4E00\u6B65\uFF1A\u8F93\u5165\u4E58\u8F66\u4FE1\u606F", TitledBorder.LEADING, TitledBorder.TOP,
null, null));
GridBagLayout gbl_panel_4 = new GridBagLayout();
gbl_panel_4.columnWidths = new int[] { 68, 100, 54, 94, 0, 80, 77, 200, 0, 0 };
gbl_panel_4.rowHeights = new int[] { 37, 0 };
gbl_panel_4.columnWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE };
gbl_panel_4.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
panel_4.setLayout(gbl_panel_4);
lblNewLabel_4 = new JLabel("起站");
GridBagConstraints gbc_lblNewLabel_4 = new GridBagConstraints();
gbc_lblNewLabel_4.insets = new Insets(0, 0, 0, 5);
gbc_lblNewLabel_4.anchor = GridBagConstraints.EAST;
gbc_lblNewLabel_4.gridx = 0;
gbc_lblNewLabel_4.gridy = 0;
panel_4.add(lblNewLabel_4, gbc_lblNewLabel_4);
textTrainFrom = new JTextField();
textTrainFrom.setToolTipText("必须填写精确的站点名称");
GridBagConstraints gbc_textTrainFrom = new GridBagConstraints();
gbc_textTrainFrom.insets = new Insets(0, 0, 0, 5);
gbc_textTrainFrom.fill = GridBagConstraints.HORIZONTAL;
gbc_textTrainFrom.gridx = 1;
gbc_textTrainFrom.gridy = 0;
panel_4.add(textTrainFrom, gbc_textTrainFrom);
textTrainFrom.setColumns(10);
lblNewLabel_5 = new JLabel("到站");
GridBagConstraints gbc_lblNewLabel_5 = new GridBagConstraints();
gbc_lblNewLabel_5.insets = new Insets(0, 0, 0, 5);
gbc_lblNewLabel_5.anchor = GridBagConstraints.EAST;
gbc_lblNewLabel_5.gridx = 2;
gbc_lblNewLabel_5.gridy = 0;
panel_4.add(lblNewLabel_5, gbc_lblNewLabel_5);
textTrainTo = new JTextField();
textTrainTo.setToolTipText("必须填写精确的站点名称");
GridBagConstraints gbc_textTrainTo = new GridBagConstraints();
gbc_textTrainTo.fill = GridBagConstraints.HORIZONTAL;
gbc_textTrainTo.insets = new Insets(0, 0, 0, 5);
gbc_textTrainTo.gridx = 3;
gbc_textTrainTo.gridy = 0;
panel_4.add(textTrainTo, gbc_textTrainTo);
textTrainTo.setColumns(10);
lblNewLabel_6 = new JLabel("乘车日期");
GridBagConstraints gbc_lblNewLabel_6 = new GridBagConstraints();
gbc_lblNewLabel_6.insets = new Insets(0, 0, 0, 5);
gbc_lblNewLabel_6.anchor = GridBagConstraints.EAST;
gbc_lblNewLabel_6.gridx = 4;
gbc_lblNewLabel_6.gridy = 0;
panel_4.add(lblNewLabel_6, gbc_lblNewLabel_6);
textPrimaryTrainDate = new JTextField();
textPrimaryTrainDate.setToolTipText("每次启动自动设定为当前日期20天后预售期");
GridBagConstraints gbc_textPrimaryTrainDate = new GridBagConstraints();
gbc_textPrimaryTrainDate.insets = new Insets(0, 0, 0, 5);
gbc_textPrimaryTrainDate.fill = GridBagConstraints.HORIZONTAL;
gbc_textPrimaryTrainDate.gridx = 5;
gbc_textPrimaryTrainDate.gridy = 0;
panel_4.add(textPrimaryTrainDate, gbc_textPrimaryTrainDate);
textPrimaryTrainDate.setColumns(10);
label = new JLabel("备选日期");
GridBagConstraints gbc_label = new GridBagConstraints();
gbc_label.anchor = GridBagConstraints.EAST;
gbc_label.insets = new Insets(0, 0, 0, 5);
gbc_label.gridx = 6;
gbc_label.gridy = 0;
panel_4.add(label, gbc_label);
textExtraTrainDates = new JTextField();
textExtraTrainDates.setToolTipText("主要用在指定多个日期刷“退票”");
textExtraTrainDates.setColumns(10);
GridBagConstraints gbc_textExtraTrainDates = new GridBagConstraints();
gbc_textExtraTrainDates.insets = new Insets(0, 0, 0, 5);
gbc_textExtraTrainDates.fill = GridBagConstraints.HORIZONTAL;
gbc_textExtraTrainDates.gridx = 7;
gbc_textExtraTrainDates.gridy = 0;
panel_4.add(textExtraTrainDates, gbc_textExtraTrainDates);
lblNewLabel = new JLabel("格式:按照预计乘车“日”优先级逗号分隔填写,如20,19,18,14");
GridBagConstraints gbc_lblNewLabel = new GridBagConstraints();
gbc_lblNewLabel.gridx = 8;
gbc_lblNewLabel.gridy = 0;
panel_4.add(lblNewLabel, gbc_lblNewLabel);
userPanelContainer = new JPanel();
userPanelContainer.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"),
"\u7B2C\u4E8C\u6B65\uFF1A\u7528\u6237\u53CA\u8F66\u6B21\u8BBE\u7F6E", TitledBorder.LEADING,
TitledBorder.TOP, null, null));
GridBagConstraints gbc_userPanelContainer = new GridBagConstraints();
gbc_userPanelContainer.fill = GridBagConstraints.BOTH;
gbc_userPanelContainer.insets = new Insets(0, 0, 5, 0);
gbc_userPanelContainer.gridx = 0;
gbc_userPanelContainer.gridy = 1;
m_contentPane.add(userPanelContainer, gbc_userPanelContainer);
userPanelContainer.setLayout(new GridLayout(0, 1, 0, 0));
passengerPanelContainer = new JPanel();
passengerPanelContainer.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "\u7B2C\u4E09\u6B65\uFF1A\u4E58\u8F66\u4EBA\u4FE1\u606F", TitledBorder.LEADING, TitledBorder.TOP, null, null));
GridBagConstraints gbc_passengerPanelContainer = new GridBagConstraints();
gbc_passengerPanelContainer.fill = GridBagConstraints.HORIZONTAL;
gbc_passengerPanelContainer.insets = new Insets(0, 0, 5, 0);
gbc_passengerPanelContainer.gridx = 0;
gbc_passengerPanelContainer.gridy = 2;
m_contentPane.add(passengerPanelContainer, gbc_passengerPanelContainer);
panelOperation = new JPanel();
GridBagConstraints gbc_panelOperation = new GridBagConstraints();
gbc_panelOperation.fill = GridBagConstraints.BOTH;
gbc_panelOperation.insets = new Insets(0, 0, 5, 0);
gbc_panelOperation.gridx = 0;
gbc_panelOperation.gridy = 3;
m_contentPane.add(panelOperation, gbc_panelOperation);
panelOperation.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
參考資料
那這次的課程就介紹到這邊囉~
順帶一提,KT 線上教室,臉書粉絲團,會不定期發佈相關資訊,不想錯過最新資訊,不要忘記來按讚,加追蹤喔!也歡迎大家將這套課程分享給更多人喔。
我們下次再見囉!!!掰掰~