# Swing 布局管理
> 原文: [http://zetcode.com/tutorials/javaswingtutorial/swinglayoutmanagement/](http://zetcode.com/tutorials/javaswingtutorial/swinglayoutmanagement/)
Java Swing 具有兩種組件:容器和子組件。 容器將子項分組為合適的布局。 要創建布局,我們使用布局管理器。
[Tweet](https://twitter.com/share)
ZetCode 為 Swing 布局管理過程提供了 196 頁專門的電子書: [Java Swing 布局管理教程](/ebooks/javaswinglayout/)
## Swing 布局管理器
Swing 有大量可用的布局管理器-內置和第三方。 但是,大多數管理器都不適合現代 UI 的創建。
有三種可以正確完成工作的布局管理器:
* `MigLayout`
* `GroupLayout`
* `FormLayout`
`MigLayout`,`GroupLayout`和`FormLayout`是強大,靈活的布局管理器,可以滿足大多數布局要求。 在本教程中,我們使用`GroupLayout`管理器來設計用戶界面。
以下布局管理器已過時:
* `FlowLayout`
* `GridLayout`
* `CardLayout`
* `BoxLayout`
* `GridBagLayout`
這些布局管理器無法滿足現代 UI 的要求。
## 過時的管理器遇到的問題
過時的管理器要么太簡單(`FlowLayout`,`GridLayout`),要么就是不必要的復雜(`GridBagLayout`)。 所有這些管理器都有一個基本的設計錯誤:他們使用組件之間的固定間隙。 在組件之間使用剛性空間是不可移植的:一旦在不同的屏幕分辨率下運行程序,用戶界面就會損壞。
過時的管理器試圖通過一種稱為嵌套的技術來修復其弱點。 在嵌套中,開發者在多個面板中使用幾個不同的布局管理器。 盡管可以使用嵌套創建 UI,但它給代碼帶來了額外的不必要的復雜性。
## 過時的管理器
在本節中,我們將介紹過時的布局管理器。 不建議使用這些管理器。 如果我們需要維護一些遺留代碼,只需花一些時間研究它們。 否則,應拒絕使用它們。
### `FlowLayout`管理器
這是 Java Swing 工具箱中最簡單的布局管理器。 它是`JPanel`組件的默認布局管理器。
它是如此簡單,以至于不能用于任何實際布局。 許多 Java Swing 教程都介紹了該管理器,因此,初學者嘗試在其項目中使用它,而沒有意識到它不能用于任何嚴重的事情。
在計算其子大小時,流程布局使每個組件都假定其自然(首選)大小。 管理器將組件排成一排。 按順序添加了它們。 如果它們不適合一排,則進入下一排。 可以從右向左添加組件,反之亦然。 管理器允許對齊組件。 隱式地,組件居中,并且組件之間以及組件的邊緣與容器的邊緣之間有 5px 的空間。
```java
FlowLayout()
FlowLayout(int align)
FlowLayout(int align, int hgap, int vgap)
```
FlowLayout 管理器有三個可用的構造器。 第一個創建具有隱式值的管理器。 以 5px 水平和垂直空間居中。 其他允許指定這些參數。
`FlowLayoutEx.java`
```java
package com.zetcode;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTree;
import java.awt.Dimension;
import java.awt.EventQueue;
public class FlowLayoutEx extends JFrame {
public FlowLayoutEx() {
initUI();
}
private void initUI() {
var panel = new JPanel();
var button = new JButton("button");
panel.add(button);
var tree = new JTree();
panel.add(tree);
var area = new JTextArea("text area");
area.setPreferredSize(new Dimension(100, 100));
panel.add(area);
add(panel);
pack();
setTitle("FlowLayout example");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new FlowLayoutEx();
ex.setVisible(true);
});
}
}
```
該示例顯示了窗口中的按鈕,樹組件和文本區域組件。 如果我們創建一個空樹組件,則組件內部會有一些默認值。
```java
var panel = new JPanel();
```
`JPanel`組件的隱式布局管理器是`FlowLayout`。 我們不必手動設置。
```java
var area = new JTextArea("text area");
area.setPreferredSize(new Dimension(100, 100));
```
流布局管理器為其組件設置首選大小。 因此,在我們的案例中,區域組件將為`100x100px`。 如果我們未設置首選大小,則組件將具有其文本的大小。 沒有文本,該組件將根本不可見。 嘗試在區域組件中編寫或刪除一些文本。 組件將相應地增長和收縮。
```java
panel.add(area);
```
該組件放置在帶有`add()`的容器內。

圖:`FlowLayout`
### `GridLayout`
`GridLayout`布局管理器將組件布置在矩形網格中。 容器分為大小相等的矩形。 每個矩形中放置一個組件。
`GridLayout`非常簡單,不能用于任何實際布局。
`GridLayoutEx.java`
```java
package com.zetcode;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.EventQueue;
import java.awt.GridLayout;
public class GridLayoutEx extends JFrame {
public GridLayoutEx() {
initUI();
}
private void initUI() {
var panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.setLayout(new GridLayout(5, 4, 5, 5));
String[] buttons = {
"Cls", "Bck", "", "Close", "7", "8", "9", "/", "4",
"5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+"
};
for (int i = 0; i < buttons.length; i++) {
if (i == 2) {
panel.add(new JLabel(buttons[i]));
} else {
panel.add(new JButton(buttons[i]));
}
}
add(panel);
setTitle("GridLayout");
setSize(350, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new GridLayoutEx();
ex.setVisible(true);
});
}
}
```
該示例顯示了一個簡單計算器工具的框架。 我們在管理器中放入了 19 個按鈕和一個標簽。 請注意,每個按鈕的大小均相同。
```java
panel.setLayout(new GridLayout(5, 4, 5, 5));
```
在這里,我們為面板組件設置了網格布局管理器。 布局管理器采用四個參數。 行數,列數以及組件之間的水平和垂直間隙。

圖:`GridLayout`
### `BorderLayout`
`BorderLayout`是一個簡單的布局管理器,在某些布局中可以派上用場。 它是`JFrame`,`JWindow`,`JDialog`,`JInternalFrame`和`JApplet`的默認布局管理器。 它有一個嚴重的局限性-它以像素為單位設置子元素之間的間隙,從而創建了剛性的布局。 這導致了不可移植的 UI,因此不建議使用它。
`BorderLayout`將空間分為五個區域:北,西,南,東和中心。 每個區域只能有一個組件。 如果需要在一個區域中放置更多組件,則必須在其中放置一個由我們選擇的管理器組成的小組。 N,W,S,E 區域中的組件具有首選大小。 中間的組件占據了剩余的整個空間。
如果子組件彼此之間距離太近,則看起來不太好。 我們必須在它們之間留一些空間。 Swing 工具箱中的每個組件的邊緣都可以帶有邊框。 要創建邊框,我們可以創建`EmptyBorder`類的新實例,或者使用`BorderFactory`。
`BorderEx.java`
```java
package com.zetcode;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
public class BorderLayoutEx extends JFrame {
public BorderLayoutEx() {
initUI();
}
private void initUI() {
var bottomPanel = new JPanel(new BorderLayout());
var topPanel = new JPanel();
topPanel.setBackground(Color.gray);
topPanel.setPreferredSize(new Dimension(250, 150));
bottomPanel.add(topPanel);
bottomPanel.setBorder(new EmptyBorder(new Insets(20, 20, 20, 20)));
add(bottomPanel);
pack();
setTitle("BorderLayout");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new BorderLayoutEx();
ex.setVisible(true);
});
}
}
```
該示例將顯示一個灰色面板及其周圍的邊框。
```java
var bottomPanel = new JPanel(new BorderLayout());
var topPanel = new JPanel();
```
我們將面板放入面板中。 底部面板具有`BorderLayout`管理器。
```java
bottomPanel.add(topPanel);
```
在這里,我們將頂部面板放入底部面板組件中。 更準確地說,我們將其放置在`BorderLayout`管理器的中心區域。
```java
bottomPanel.setBorder(new EmptyBorder(new Insets(20, 20, 20, 20)));
```
在這里,我們在底部面板周圍創建了 20px 的邊框。 邊框值如下:上,左,下和右。 請注意,創建固定的嵌入(空格)不是可移植的。

圖:`BorderLayout`
下一個示例顯示`BorderLayout`管理器的典型用法。
`BorderLayoutEx2.java`
```java
package com.zetcode;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.border.EmptyBorder;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Insets;
public class BorderLayoutEx2 extends JFrame {
public BorderLayoutEx2() {
initUI();
}
private void initUI() {
var menubar = new JMenuBar();
var fileMenu = new JMenu("File");
menubar.add(fileMenu);
setJMenuBar(menubar);
var toolbar = new JToolBar();
toolbar.setFloatable(false);
var exitIcon = new ImageIcon("src/resources/exit.png");
var exitBtn = new JButton(exitIcon);
exitBtn.setBorder(new EmptyBorder(0, 0, 0, 0));
toolbar.add(exitBtn);
add(toolbar, BorderLayout.NORTH);
var vertical = new JToolBar(JToolBar.VERTICAL);
vertical.setFloatable(false);
vertical.setMargin(new Insets(10, 5, 5, 5));
var driveIcon = new ImageIcon("src/resources/drive.png");
var compIcon = new ImageIcon("src/resources/computer.png");
var printIcon = new ImageIcon("src/resources/printer.png");
var driveBtn = new JButton(driveIcon);
driveBtn.setBorder(new EmptyBorder(3, 0, 3, 0));
var compBtn = new JButton(compIcon);
compBtn.setBorder(new EmptyBorder(3, 0, 3, 0));
var printBtn = new JButton(printIcon);
printBtn.setBorder(new EmptyBorder(3, 0, 3, 0));
vertical.add(driveBtn);
vertical.add(compBtn);
vertical.add(printBtn);
add(vertical, BorderLayout.WEST);
add(new JTextArea(), BorderLayout.CENTER);
var statusbar = new JLabel(" Statusbar");
add(statusbar, BorderLayout.SOUTH);
setSize(400, 350);
setTitle("BorderLayout");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new BorderLayoutEx2();
ex.setVisible(true);
});
}
}
```
該示例顯示了典型的應用框架。 我們顯示了一個垂直和水平工具欄,一個狀態欄和一個中央組件(文本區域)。
`BorderLayout`是`JFrame`容器的默認布局管理器。 因此,我們不必顯式設置它。
```java
add(toolbar, BorderLayout.NORTH);
```
我們將工具欄放置在布局的北部。
```java
var driveBtn = new JButton(driveIcon);
driveBtn.setBorder(new EmptyBorder(3, 0, 3, 0));
```
為了在按鈕周圍留一些空白,我們必須使用`EmptyBorder`。 這會在按鈕的頂部和底部增加一些固定的空間。 當我們添加固定空間時,UI 不可移植。 3px 的空間在 1280x720 的屏幕上可能看起來不錯,但在`1920x1200px`的屏幕上不合適。
```java
add(vertical, BorderLayout.WEST);
```
我們將垂直太桿放在西邊。
```java
add(new JTextArea(), BorderLayout.CENTER);
```
我們將文本區域放置在中間。
```java
add(statusbar, BorderLayout.SOUTH);
```
狀態欄轉到南部區域。

圖:`BorderLayout` 2
### `CardLayout`
`CardLayout`是一個簡單的布局管理器,將每個組件都視為卡。 容器是這些卡的棧。 一次只能看到一個組件。 其余的隱藏。 最初顯示容器時,默認情況下將顯示添加到容器的第一個組件。 該管理器的實際用途有限。 它可用于創建向導或選項卡式窗格。
以下示例使用`CardLayout`管理器創建圖像庫。 我們使用了 Krasna Horka 城堡的四張圖片(2012 年大火之前)。
`CardLayoutEx.java`
```java
package com.zetcode;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class CardLayoutEx extends JFrame {
private ImageIcon horka1;
private ImageIcon horka2;
private ImageIcon horka3;
private ImageIcon horka4;
private ImageIcon previ;
private ImageIcon nexti;
private JPanel mainPanel;
private CardLayout cardLayout;
public CardLayoutEx() {
initUI();
}
private void initUI() {
mainPanel = new JPanel();
mainPanel.setBackground(new Color(50, 50, 50));
mainPanel.setBorder(
BorderFactory.createEmptyBorder(5, 5, 5, 5)
);
cardLayout = new CardLayout();
mainPanel.setLayout(cardLayout);
horka1 = new ImageIcon("src/resources/horka1.jpg");
horka2 = new ImageIcon("src/resources/horka2.jpg");
horka3 = new ImageIcon("src/resources/horka3.jpg");
horka4 = new ImageIcon("src/resources/horka4.jpg");
previ = new ImageIcon("src/resources/previous.png");
nexti = new ImageIcon("src/resources/next.png");
var label1 = new JLabel(horka1);
var label2 = new JLabel(horka2);
var label3 = new JLabel(horka3);
var label4 = new JLabel(horka4);
mainPanel.add(label1);
mainPanel.add(label2);
mainPanel.add(label3);
mainPanel.add(label4);
add(mainPanel);
var prevButton = new JButton(previ);
prevButton.addActionListener((e) -> cardLayout.previous(mainPanel));
var nextButton = new JButton(nexti);
nextButton.addActionListener((e) -> cardLayout.next(mainPanel));
var btnPanel = new JPanel();
btnPanel.setBackground(new Color(50, 50, 50));
btnPanel.add(prevButton);
btnPanel.add(nextButton);
add(btnPanel, BorderLayout.SOUTH);
pack();
setTitle("Gallery");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new CardLayoutEx();
ex.setVisible(true);
});
}
}
```
我們創建兩個按鈕來瀏覽圖像。
```java
mainPanel = new JPanel();
mainPanel.setBackground(new Color(50, 50, 50));
mainPanel.setBorder(
BorderFactory.createEmptyBorder(5, 5, 5, 5)
);
```
我們創建主面板組件。 我們將其顏色設置為深灰色。 我們將 5px 放置在面板周圍,以使它的子級不太靠近窗口的邊界。
```java
cardLayout = new CardLayout();
mainPanel.setLayout(cardLayout);
```
`CardLayout`管理器已創建并設置到主面板。
```java
mainPanel.add(label1);
mainPanel.add(label2);
mainPanel.add(label3);
mainPanel.add(label4);
```
顯示圖像的標簽組件將添加到面板中。
```java
var prevButton = new JButton(previ);
prevButton.addActionListener((e) -> cardLayout.previous(mainPanel));
```
單擊上一個按鈕,將調用管理器的`previous()`方法。 它會翻轉到指定容器的上一張卡片。
```java
add(mainPanel);
```
我們將主面板添加到框架組件邊框布局的中心區域。 如果未明確指定放置組件的位置,則會將其添加到中心區域。
```java
var btnPanel = new JPanel();
btnPanel.setBackground(new Color(50, 50, 50));
btnPanel.add(prevButton);
btnPanel.add(nextButton);
```
這些按鈕將添加到按鈕面板。
```java
add(btnPanel, BorderLayout.SOUTH);
```
最后,將帶有按鈕的面板放入`BorderLayout`管理器的南部區域。

圖:`CardLayout`
### `BoxLayout`
`BoxLayout`管理器是一個簡單的布局管理器,用于組織列或行中的組件。 它可以使用嵌套創建非常復雜的布局。 但是,這增加了布局創建的復雜性,并使用了額外的資源,尤其是許多其他`JPanel`組件。 `BoxLayout`僅能創建固定空間; 因此,其布局不可移植。
`BoxLayout`具有以下構造器:
```java
BoxLayout(Container target, int axis)
```
構造器創建一個布局管理器,該管理器將沿給定軸布置組件。 與其他布局管理器不同,`BoxLayout`將容器實例作為構造器中的第一個參數。 第二個參數確定管理器的方向。 要創建一個水平框,我們可以使用`LINE_AXIS`常量。 要創建一個垂直框,我們可以使用`PAGE_AXIS`常量。
框布局管理器通常與`Box`類一起使用。 此類創建一些不可見的組件,這些組件會影響最終布局。
* 膠水
* 支撐
* 剛性區域
假設我們要在窗口的右下角放置兩個按鈕。
`BoxLayoutButtonsEx.java`
```java
package com.zetcode;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Dimension;
import java.awt.EventQueue;
public class BoxLayoutButtonsEx extends JFrame {
public BoxLayoutButtonsEx() {
initUI();
}
private void initUI() {
var basePanel = new JPanel();
basePanel.setLayout(new BoxLayout(basePanel, BoxLayout.Y_AXIS));
add(basePanel);
basePanel.add(Box.createVerticalGlue());
var bottomPanel = new JPanel();
bottomPanel.setAlignmentX(1f);
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS));
var okBtn = new JButton("OK");
var closeBtn = new JButton("Close");
bottomPanel.add(okBtn);
bottomPanel.add(Box.createRigidArea(new Dimension(5, 0)));
bottomPanel.add(closeBtn);
bottomPanel.add(Box.createRigidArea(new Dimension(15, 0)));
basePanel.add(bottomPanel);
basePanel.add(Box.createRigidArea(new Dimension(0, 15)));
setTitle("Two Buttons");
setSize(300, 150);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new BoxLayoutButtonsEx();
ex.setVisible(true);
});
}
}
```
下圖說明了該示例。

圖:兩個按鈕
我們創建兩個面板。 基本面板具有垂直框布局。 底部面板有一個水平面板。 我們將底板插入底板。 底部面板右對齊。 窗口頂部和底部面板之間的空間是可擴展的。 這是通過垂直膠水實現的。
```java
basePanel.setLayout(new BoxLayout(basePanel, BoxLayout.Y_AXIS));
```
在這里,我們使用垂直`BoxLayout`創建一個基礎面板。
```java
var bottomPanel = new JPanel();
bottomPanel.setAlignmentX(1f);
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS));
```
底部面板右對齊。 這是通過`setAlignmentX()`方法完成的。 面板具有水平布局。
```java
bottomPanel.add(Box.createRigidArea(new Dimension(5, 0)));
```
我們在按鈕之間留出一些剛性空間。
```java
basePanel.add(bottomPanel);
```
在這里,我們將具有水平框布局的底部面板放置到垂直基礎面板上。
```java
basePanel.add(Box.createRigidArea(new Dimension(0, 15)));
```
我們還在底部面板和窗口邊框之間留出一些空間。

圖:`BoxLayout`按鈕示例
當使用`BoxLayout`管理器時,可以在組件之間設置一個剛性區域。
`BoxLayoutRigidAreaEx.java`
```java
package com.zetcode;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
public class BoxLayoutRigidAreaEx extends JFrame {
public BoxLayoutRigidAreaEx() {
initUI();
}
private void initUI() {
var basePanel = new JPanel();
basePanel.setLayout(new BoxLayout(basePanel, BoxLayout.Y_AXIS));
basePanel.setBorder(new EmptyBorder(new Insets(40, 60, 40, 60)));
basePanel.add(new JButton("Button"));
basePanel.add(Box.createRigidArea(new Dimension(0, 5)));
basePanel.add(new JButton("Button"));
basePanel.add(Box.createRigidArea(new Dimension(0, 5)));
basePanel.add(new JButton("Button"));
basePanel.add(Box.createRigidArea(new Dimension(0, 5)));
basePanel.add(new JButton("Button"));
add(basePanel);
pack();
setTitle("RigidArea");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new BoxLayoutRigidAreaEx();
ex.setVisible(true);
});
}
}
```
在此示例中,我們顯示四個按鈕。 默認情況下,按鈕之間沒有空格。 為了在其中留出一些空間,我們增加了一些剛性區域。
```java
basePanel.setLayout(new BoxLayout(basePanel, BoxLayout.Y_AXIS));
```
我們為面板使用垂直`BoxLayout`管理器。
```java
basePanel.add(new JButton("Button"));
basePanel.add(Box.createRigidArea(new Dimension(0, 5)));
basePanel.add(new JButton("Button"));
```
我們添加按鈕并使用`Box.createRigidArea()`在它們之間創建一個剛性區域。

圖:`RigidArea`
### 每日提示
下一個示例創建“每日提示”窗口對話框。 我們結合使用各種布局管理器。
`TipOfDayEx.java`
```java
package com.zetcode;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextPane;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.KeyEvent;
public class TipOfDayEx extends JDialog {
public TipOfDayEx() {
initUI();
}
private void initUI() {
var basePanel = new JPanel();
basePanel.setLayout(new BoxLayout(basePanel, BoxLayout.Y_AXIS));
add(basePanel);
var topPanel = new JPanel(new BorderLayout(0, 0));
topPanel.setMaximumSize(new Dimension(450, 0));
var hint = new JLabel("Productivity Hints");
hint.setBorder(BorderFactory.createEmptyBorder(0, 25, 0, 0));
topPanel.add(hint);
var icon = new ImageIcon("src/resources/coffee2.png");
var label = new JLabel(icon);
label.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
topPanel.add(label, BorderLayout.EAST);
var separator = new JSeparator();
separator.setForeground(Color.gray);
topPanel.add(separator, BorderLayout.SOUTH);
basePanel.add(topPanel);
var textPanel = new JPanel(new BorderLayout());
textPanel.setBorder(BorderFactory.createEmptyBorder(15, 25, 15, 25));
var pane = new JTextPane();
pane.setContentType("text/html");
var text = "<p><b>Closing windows using the mouse wheel</b></p>" +
"<p>Clicking with the mouse wheel on an editor tab closes the window. " +
"This method works also with dockable windows or Log window tabs.</p>";
pane.setText(text);
pane.setEditable(false);
textPanel.add(pane);
basePanel.add(textPanel);
var boxPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 0));
var box = new JCheckBox("Show Tips at startup");
box.setMnemonic(KeyEvent.VK_S);
boxPanel.add(box);
basePanel.add(boxPanel);
var bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
var tipBtn = new JButton("Next Tip");
tipBtn.setMnemonic(KeyEvent.VK_N);
var closeBtn = new JButton("Close");
closeBtn.setMnemonic(KeyEvent.VK_C);
bottomPanel.add(tipBtn);
bottomPanel.add(closeBtn);
basePanel.add(bottomPanel);
bottomPanel.setMaximumSize(new Dimension(450, 0));
setTitle("Tip of the Day");
setSize(new Dimension(450, 350));
setResizable(false);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new TipOfDayEx();
ex.setVisible(true);
});
}
}
```
該示例混合使用了布局管理器。 只需將四個面板放入垂直組織的基本面板中即可。
```java
var basePanel = new JPanel();
basePanel.setLayout(new BoxLayout(basePanel, BoxLayout.Y_AXIS));
add(basePanel);
```
這是最底部的面板。 它具有垂直框布局管理器。 基本面板已添加到默認的`JDialog`組件。 默認情況下,此組件具有邊框布局管理器。
```java
var topPanel = new JPanel(new BorderLayout(0, 0));
```
`topPanel`面板具有邊框布局管理器。 我們將包含三個組成部分。 兩個標簽和一個分隔符。
```java
topPanel.setMaximumSize(new Dimension(450, 0));
```
如果我們想要的面板不超過其組件,則必須設置其最大大小。 零值將被忽略。 管理器計算必要的高度。
```java
var textPanel = new JPanel(new BorderLayout());
...
textPanel.add(pane);
```
文本窗格組件將添加到邊框布局管理器的中心區域。 它會占用所有剩余空間。 正是我們想要的。
```java
var boxPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 0));
```
該復選框顯示在`boxPanel`面板中。 它保持對齊。 流布局管理器的水平間隙為 20px。 其他組件的像素為 25px。 這是為什么? 這是因為流布局管理器也在組件和邊緣之間放置了一些空間。
```java
var bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
...
bottomPanel.setMaximumSize(new Dimension(450, 0));
```
底部面板顯示兩個按鈕。 它具有右對齊的流布局管理器。 為了在對話框的右邊緣顯示按鈕,面板必須從頭到尾水平伸展。

圖:當天的提示
## 沒有管理器
可以不使用布局管理器。 在少數情況下,我們可能不需要布局管理器。 (也許將一些圖像放置在一些不規則的位置。)但是在大多數情況下,要創建真正可移植的復雜應用,我們需要布局管理器。
如果沒有布局管理器,我們將使用絕對值來定位組件。
`AbsoluteLayoutEx.java`
```java
package com.zetcode;
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.EventQueue;
public class AbsoluteLayoutEx extends JFrame {
public AbsoluteLayoutEx() {
initUI();
}
private void initUI() {
setLayout(null);
var okBtn = new JButton("OK");
okBtn.setBounds(50, 50, 80, 25);
var closeBtn = new JButton("Close");
closeBtn.setBounds(150, 50, 80, 25);
add(okBtn);
add(closeBtn);
setTitle("Absolute positioning");
setSize(300, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var ex = new AbsoluteLayoutEx();
ex.setVisible(true);
});
}
}
```
這個簡單的示例顯示了兩個按鈕。
```java
setLayout(null);
```
我們通過向`setLayout()`方法提供`null`使用絕對定位。 (`JFrame`組件具有默認的布局管理器`BorderLayout`。)
```java
okBtn.setBounds(50, 50, 80, 25);
```
`setBounds()`方法放置“確定”按鈕。 參數是 x 和 y 坐標以及組件的寬度和高度。

圖:絕對布局
在本章中,我們提到了 Swing 中的布局管理。
- ZetCode 數據庫教程
- MySQL 教程
- MySQL 簡介
- MySQL 安裝
- MySQL 的第一步
- MySQL 快速教程
- MySQL 存儲引擎
- MySQL 數據類型
- 在 MySQL 中創建,更改和刪除表
- MySQL 表達式
- 在 MySQL 中插入,更新和刪除數據
- MySQL 中的SELECT語句
- MySQL 子查詢
- MySQL 約束
- 在 MySQL 中導出和導入數據
- 在 MySQL 中連接表
- MySQL 函數
- MySQL 中的視圖
- MySQL 中的事務
- MySQL 存儲過程
- MySQL Python 教程
- MySQL Perl 教程
- MySQL & Perl DBI
- 使用 Perl 連接到 MySQL 數據庫
- MySQL 中的 Perl 錯誤處理
- 使用 Perl 進行 MySQL 查詢
- 在 MySQL 中使用 Perl 綁定參數&列
- 在 MySQL 中使用 Perl 處理圖像
- 使用 Perl 獲取 MySQL 元數據
- Perl 的 MySQL 事務
- MySQL C API 編程教程
- MySQL Visual Basic 教程
- MySQL PHP 教程
- MySQL Java 教程
- MySQL Ruby 教程
- MySQL C# 教程
- SQLite 教程
- SQLite 簡介
- sqlite3 命令行工具
- 在 SQLite 中創建,刪除和更改表
- SQLite 表達式
- SQLite 插入,更新,刪除數據
- SQLite SELECT語句
- SQLite 約束
- SQLite 連接表
- SQLite 函數
- SQLite 視圖,觸發器,事務
- SQLite C 教程
- SQLite Python 教程
- SQLite Perl 教程
- Perl DBI
- 使用 Perl 連接到 SQLite 數據庫
- SQLite Perl 錯誤處理
- 使用 Perl 的 SQLite 查詢
- 使用 Perl 綁定 SQLite 參數&列
- 使用 Perl 在 SQLite 中處理圖像
- 使用 Perl 獲取 SQLite 元數據
- 使用 Perl 進行 SQLite 事務
- SQLite Ruby 教程
- 連接到 SQLite 數據庫
- 在 SQLite 中使用 Ruby 進行 SQL 查詢
- 綁定參數
- 處理圖像
- 使用 Ruby 獲取 SQLite 元數據
- Ruby 的 SQLite 事務
- SQLite C# 教程
- SQLite C# 簡介
- 使用SqliteDataReader檢索數據
- ADO.NET 數據集
- 使用 C# 在 SQLite 中處理圖像
- 使用 C# 獲取 SQLite 元數據
- 使用 C# 的 SQLite 事務
- SQLite Visual Basic 教程
- SQLite Visual Basic 簡介
- 使用SqliteDataReader檢索數據
- ADO.NET 的數據集
- 使用 Visual Basic 在 SQLite 中處理圖像
- 使用 Visual Basic 獲取 SQLite 元數據
- 使用 Visual Basic 的 SQLite 事務
- PostgreSQL C 教程
- PostgreSQL Ruby 教程
- PostgreSQL PHP 教程
- PostgreSQL PHP 編程簡介
- 在 PostgreSQL 中使用 PHP 檢索數據
- 在 PostgreSQL 中使用 PHP 處理圖像
- 用 PHP 獲取 PostgreSQL 元數據
- 在 PostgreSQL 中使用 PHP 進行事務
- PostgreSQL Java 教程
- Apache Derby 教程
- Derby 簡介
- Derby 的安裝&配置
- Derby 工具
- ij 工具
- Derby 中的 SQL 查詢
- 在 Derby 中使用 JDBC 進行編程
- Derby 安全
- 使用 Derby & Apache Tomcat
- NetBeans 和 Derby
- SQLAlchemy 教程
- SQLAlchemy 簡介
- 原始 SQL
- 模式定義語言
- SQL 表達式語言
- SQLAlchemy 中的對象關系映射器
- MongoDB PHP 教程
- MongoDB JavaScript 教程
- MongoDB Ruby 教程
- Spring JdbcTemplate 教程
- JDBI 教程
- MyBatis 教程
- Hibernate Derby 教程
- ZetCode .NET 教程
- Visual Basic 教程
- Visual Basic
- Visual Basic 語法結構
- 基本概念
- Visual Basic 數據類型
- Visual Basic 中的字符串
- 運算符
- 控制流
- Visual Basic 數組
- Visual Basic 中的過程&函數
- 在 Visual Basic 中組織代碼
- 面向對象編程
- Visual Basic 中的面向對象編程 II
- Visual Basic 中的集合
- 輸入和輸出
- C# 教程
- C# 語言
- C# 語法結構
- C# 基礎
- C# 數據類型
- C# 中的字符串
- C# 運算符
- C# 中的流控制
- C# 數組
- C# 面向對象編程
- C# 中的方法
- C# 面向對象編程 II
- C# 屬性
- C# 結構
- C# 委托
- 命名空間
- C# 集合
- C# 輸入和輸出
- C# 目錄教程
- C# 字典教程
- 在 C# 中讀取文本文件
- C# 中的日期和時間
- 在 C# 中讀取網頁
- C# HttpClient教程
- ASP.NET Core 教程
- ZetCode 圖形教程
- Java 2D 游戲教程
- Java 游戲基礎
- 動畫
- 移動精靈
- 碰撞檢測
- Java 益智游戲
- Java Snake
- Breakout 游戲
- Java 俄羅斯方塊
- Java 吃豆人
- Java 太空侵略者
- Java 掃雷
- Java 推箱子
- Java 2D 教程
- 介紹
- 基本繪圖
- 形狀和填充
- 透明度
- 合成
- 剪裁
- 變換
- 特效
- 圖像
- 文字和字體
- 命中測試,移動物體
- 俄羅斯方塊
- Cario 圖形教程
- Cario 圖形庫
- Cario 定義
- Cairo 后端
- Cairo 基本圖形
- 形狀和填充
- 漸變
- 透明度
- 合成
- 剪裁和遮罩
- 變換
- Cairo 文字
- Cairo 中的圖像
- 根窗口
- PyCairo 教程
- PyCairo 簡介
- PyCairo 后端
- PyCairo 中的基本繪圖
- PyCairo 形狀和填充
- PyCairo 漸變
- PyCairo 剪裁&遮罩
- PyCairo 的透明度
- PyCairo 中的變換
- PyCairo 中的文字
- PyCairo 中的圖像
- 根窗口
- HTML5 畫布教程
- 介紹
- HTML5 畫布中的直線
- HTML5 畫布形狀
- HTML5 畫布填充
- HTML5 畫布中的透明度
- HTML5 畫布合成
- HTML5 canvas 中的變換
- HTML5 畫布中的文字
- HTML5 畫布中的動畫
- HTML5 畫布中的 Snake
- ZetCode GUI 教程
- Windows API 教程
- Windows API 簡介
- Windows API main函數
- Windows API 中的系統函數
- Windows API 中的字符串
- Windows API 中的日期和時間
- Windows API 中的一個窗口
- UI 的第一步
- Windows API 菜單
- Windows API 對話框
- Windows API 控件 I
- Windows API 控件 II
- Windows API 控件 III
- Windows API 中的高級控件
- Windows API 中的自定義控件
- Windows API 中的 GDI
- PyQt4 教程
- PyQt4 簡介
- PyQt4 中的第一個程序
- PyQt4 中的菜單和工具欄
- PyQt4 中的布局管理
- PyQt4 中的事件和信號
- PyQt4 中的對話框
- PyQt4 小部件
- PyQt4 小部件 II
- PyQt4 中的拖放
- PyQt4 中的繪圖
- PyQt4 中的自定義小部件
- PyQt4 中的俄羅斯方塊游戲
- PyQt5 教程
- PyQt5 簡介
- PyQt5 日期和時間
- PyQt5 中的第一個程序
- PyQt5 中的菜單和工具欄
- PyQt5 中的布局管理
- PyQt5 中的事件和信號
- PyQt5 中的對話框
- PyQt5 小部件
- PyQt5 小部件 II
- PyQt5 拖放
- PyQt5 中的繪圖
- PyQt5 中的自定義小部件
- PyQt5 中的俄羅斯方塊
- Qt4 教程
- Qt4 工具包簡介
- Qt4 工具類
- Qt4 中的字符串
- Qt4 中的日期和時間
- 在 Qt4 中使用文件和目錄
- Qt4 中的第一個程序
- Qt4 中的菜單和工具欄
- Qt4 中的布局管理
- Qt4 中的事件和信號
- Qt4 小部件
- Qt4 小部件 II
- Qt4 中的繪圖
- Qt4 中的自定義小部件
- Qt4 中的打磚塊游戲
- Qt5 教程
- Qt5 工具包簡介
- Qt5 中的字符串
- Qt5 中的日期和時間
- Qt5 中的容器
- 在 Qt5 中處理文件和目錄
- Qt5 中的第一個程序
- Qt5 中的菜單和工具欄
- Qt5 中的布局管理
- Qt5 中的事件和信號
- Qt5 小部件
- Qt5 小部件 II
- Qt5 中的繪圖
- Qt5 中的自定義小部件
- Qt5 中的貪食蛇
- Qt5 中的打磚塊游戲
- PySide 教程
- PySide 工具包簡介
- PySide 中的第一個程序
- PySide 中的菜單和工具欄
- PySide 中的布局管理
- PySide 中的事件和信號
- PySide 中的對話框
- PySide 小部件
- PySide 小部件 II
- 在 PySide 中拖放
- 在 PySide 中繪圖
- PySide 中的自定義小部件
- PySide 中的俄羅斯方塊游戲
- Tkinter 教程
- Tkinter 簡介
- Tkinter 中的布局管理
- Tkinter 標準小部件屬性
- Tkinter 小部件
- Tkinter 中的菜單和工具欄
- Tkinter 中的對話框
- Tkinter 中的繪圖
- Tkinter 中的貪食蛇
- Tcl/Tk 教程
- Tcl/Tk 簡介
- Tcl/Tk 中的布局管理
- Tcl/Tk 小部件
- Tcl/Tk 中的菜單和工具欄
- Tcl/Tk 中的對話框
- Tcl/Tk 繪圖
- 貪食蛇
- Qt 快速教程
- Java Swing 教程
- Java Swing 簡介
- Java Swing 首個程序
- Java Swing 中的菜單和工具欄
- Swing 布局管理
- GroupLayout管理器
- Java Swing 事件
- 基本的 Swing 組件
- 基本的 Swing 組件 II
- Java Swing 對話框
- Java Swing 模型架構
- Swing 中的拖放
- Swing 中的繪圖
- Java Swing 中的可調整大小的組件
- Java Swing 中的益智游戲
- 俄羅斯方塊
- JavaFX 教程
- JavaFX 簡介
- JavaFX 首個程序
- JavaFX 布局窗格
- 基本的 JavaFX 控件
- 基本 JavaFX 控件 II
- JavaFX 事件
- JavaFX 效果
- JavaFX 動畫
- JavaFX 畫布
- JavaFX 圖表
- Java SWT 教程
- Java SWT 簡介
- Java SWT 中的布局管理
- Java SWT 中的菜單和工具欄
- Java SWT 中的小部件
- Table小部件
- Java SWT 中的對話框
- Java SWT 繪圖
- Java SWT 中的貪食蛇
- wxWidgets 教程
- wxWidgets 簡介
- wxWidgets 助手類
- wxWidgets 中的第一個程序
- wxWidgets 中的菜單和工具欄
- wxWidgets 中的布局管理
- wxWidgets 中的事件
- wxWidgets 中的對話框
- wxWidgets 小部件
- wxWidgets 小部件 II
- wxWidgets 中的拖放
- wxWidgets 中的設備上下文
- wxWidgets 中的自定義小部件
- wxWidgets 中的俄羅斯方塊游戲
- wxPython 教程
- wxPython 簡介
- 第一步
- 菜單和工具欄
- wxPython 中的布局管理
- wxPython 中的事件
- wxPython 對話框
- 小部件
- wxPython 中的高級小部件
- wxPython 中的拖放
- wxPython 圖形
- 創建自定義小部件
- wxPython 中的應用框架
- wxPython 中的俄羅斯方塊游戲
- C# Winforms Mono 教程
- Mono Winforms 簡介
- Mono Winforms 中的第一步
- Mono Winforms 中的布局管理
- Mono Winforms 中的菜單和工具欄
- Mono Winforms 中的基本控件
- Mono Winforms 中的高級控件
- 對話框
- Mono Winforms 中的拖放
- Mono Winforms 中的繪圖
- Mono Winforms 中的貪食蛇
- Java Gnome 教程
- Java Gnome 簡介
- Java Gnome 的第一步
- Java Gnome 中的布局管理
- Java Gnome 中的布局管理 II
- Java Gnome 中的菜單
- Java Gnome 中的工具欄
- Java Gnome 中的事件
- Java Gnome 中的小部件
- Java Gnome 中的小部件 II
- Java Gnome 中的高級小部件
- Java Gnome 中的對話框
- Java Gnome 中的 Pango
- 在 Java Gnome 中用 Cairo 繪圖
- Cario 繪圖 II
- Java Gnome 中的貪食蛇
- QtJambi 教程
- QtJambi 簡介
- QtJambi 中的布局管理
- QtJambi 中的小部件
- QtJambi 中的菜單和工具欄
- QtJambi 對話框
- QtJambi 中的繪圖
- QtJambi 中的自定義小部件
- 貪食蛇
- GTK+ 教程
- GTK+ 簡介
- GTK+ 中的第一個程序
- GTK+ 中的菜單和工具欄
- GTK+ 布局管理
- GTK+ 事件和信號
- GTK+ 對話框
- GTK+ 小部件
- GTK+ 小部件 II
- GtkTreeView小部件
- GtkTextView小部件
- 自定義 GTK+ 小部件
- Ruby GTK 教程
- Ruby GTK 簡介
- Ruby GTK 中的布局管理
- Ruby GTK 中的小部件
- Ruby GTK 中的菜單和工具欄
- Ruby GTK 中的對話框
- Ruby GTK Cario 繪圖
- Ruby GTK 中的自定義小部件
- Ruby GTK 中的貪食蛇
- GTK# 教程
- GTK# 簡介
- GTK 的第一步
- GTK# 中的布局管理
- GTK 中的菜單
- GTK# 中的工具欄
- GTK# 中的事件
- GTK# 中的小部件
- GTK 中的小部件 II
- GTK# 中的高級小部件
- GTK# 中的對話框
- Pango
- GTK# 中的 Cario 繪圖
- GTK# 中的 Cario 繪圖 II
- GTK# 中的自定義小部件
- Visual Basic GTK# 教程
- Visual Basic GTK# 簡介
- 布局管理
- 小部件
- 菜單和工具欄
- 對話框
- Cario 繪圖
- 自定義小部件
- 貪食蛇
- PyGTK 教程
- PyGTK 簡介
- PyGTK 的第一步
- PyGTK 中的布局管理
- PyGTK 中的菜單
- PyGTK 中的工具欄
- PyGTK 中的事件和信號
- PyGTK 中的小部件
- PyGTK 中的小部件 II
- PyGTK 中的高級小部件
- PyGTK 中的對話框
- Pango
- Pango II
- PyGTK 中的 Cario 繪圖
- Cario 繪圖 II
- PyGTK 中的貪食蛇游戲
- PyGTK 中的自定義小部件
- PHP GTK 教程
- PHP GTK 簡介
- PHP GTK 中的布局管理
- PHP GTK 中的小部件
- PHP GTK 中的菜單和工具欄
- 對話框
- Cario 繪圖
- 自定義小部件
- 貪食蛇
- C# Qyoto 教程
- Qyoto 介紹
- 布局管理
- Qyoto 中的小部件
- Qyoto 中的菜單和工具欄
- Qyoto 對話框
- Qyoto 中的繪圖
- Qyoto 中的繪圖 II
- Qyoto 中的自定義小部件
- 貪食蛇
- Ruby Qt 教程
- Ruby Qt 簡介
- Ruby Qt 中的布局管理
- Ruby Qt 中的小部件
- 菜單和工具欄
- Ruby Qt 中的對話框
- 用 Ruby Qt 繪圖
- Ruby Qt 中的自定義小部件
- Ruby Qt 中的貪食蛇
- Visual Basic Qyoto 教程
- Qyoto 介紹
- 布局管理
- Qyoto 中的小部件
- Qyoto 中的菜單和工具欄
- Qyoto 對話框
- Qyoto 中的繪圖
- Qyoto 中的自定義小部件
- 貪食蛇
- Mono IronPython Winforms 教程
- 介紹
- IronPython Mono Winforms 中的第一步
- 布局管理
- 菜單和工具欄
- Mono Winforms 中的基本控件
- Mono Winforms 中的基本控件 II
- Mono Winforms 中的高級控件
- 對話框
- Mono Winforms 中的拖放
- 繪圖
- IronPython Mono Winforms 中的繪圖 II
- IronPython Mono Winforms 中的貪食蛇
- IronPython Mono Winforms 中的俄羅斯方塊游戲
- FreeBASIC GTK 教程
- Jython Swing 教程
- Jython Swing 簡介
- Jython Swing 中的布局管理
- Jython Swing 中的組件
- Jython Swing 中的菜單和工具欄
- Jython Swing 中的對話框
- Jython Swing 中的繪圖
- Jython Swing 中的半字節
- JRuby Swing 教程
- JRuby Swing 簡介
- JRuby Swing 中的布局管理
- JRuby Swing 中的組件
- 菜單和工具欄
- JRuby Swing 中的對話框
- 在 JRuby Swing 中繪圖
- JRuby Swing 中的貪食蛇
- Visual Basic Winforms 教程
- Visual Basic Winforms 簡介
- 布局管理
- 基本控制
- 進階控件
- 菜單和工具欄
- 對話框
- 繪圖
- 拖放
- 貪食蛇
- JavaScript GTK 教程
- JavaScript GTK 簡介
- 布局管理
- JavaScript GTK 中的小部件
- JavaScript GTK 中的菜單和工具欄
- JavaScript GTK 中的對話框
- JavaScript GTK 中的 Cario 繪圖
- ZetCode Java 教程
- Java 教程
- Java 語言
- Java 語法結構
- Java 基礎
- Java 數據類型
- Java 數據類型 II
- Java 字符串
- Java 數組
- Java 表達式
- Java 控制流程
- Java 面向對象的編程
- Java 方法
- Java 面向對象編程 II
- Java 包
- Java 中的異常
- Java 集合
- Java 流
- Java Future 教程
- Java Comparable和Comparator
- Java DOM 教程
- Java MVC 教程
- Java SAX 教程
- Java JAXB 教程
- Java JSON 處理教程
- Java H2 教程
- MongoDB Java 教程
- Java 正則表達式教程
- Java PDFBox 教程
- Java 文件教程
- Java Files.list教程
- Java Files.walk教程
- Java DirectoryStream教程
- Java 外部與內部迭代器
- Java 文件大小
- 用 Java 創建目錄
- 用 Java 創建文件
- Java Log4j 教程
- Gson 教程
- Java RequestDispatcher
- Java HTTP GET/POST 請求
- Java InputStream教程
- Java FileOutputStream教程
- Java FileInputStream教程
- Java ZipInputStream教程
- Java FileWriter教程
- EJB 簡介
- Java forEach教程
- Jetty 教程
- Tomcat Derby 教程
- Stripes 介紹
- 使用 Stripes 的 Java webapp,MyBatis,& Derby
- EclipseLink 簡介
- Java 中的數據源
- JSTL 中的 SQL 查詢標記
- Java 驗證過濾器
- Hibernate 驗證器
- 用 Java 顯示圖像
- Play 框架簡介
- Spark Java 簡介
- Java ResourceBundle教程
- Jtwig 教程
- Java Servlet 教程
- Java 套接字教程
- FreeMarker 教程
- Android 教程
- Java EE 5 教程
- JSoup 教程
- JFreeChart 教程
- ImageIcon教程
- 用 Java 復制文件
- Java 文件時間教程
- 如何使用 Java 獲取當前日期時間
- Java 列出目錄內容
- Java 附加到文件
- Java ArrayList教程
- 用 Java 讀寫 ICO 圖像
- Java int到String的轉換
- Java HashSet教程
- Java HashMap教程
- Java static關鍵字
- Java 中的HashMap迭代
- 用 Java 過濾列表
- 在 Java 中讀取網頁
- Java 控制臺應用
- Java 集合的便利工廠方法
- Google Guava 簡介
- OpenCSV 教程
- 用 Java8 的StringJoiner連接字符串
- Java 中元素迭代的歷史
- Java 謂詞
- Java StringBuilder
- Java 分割字串教學
- Java NumberFormat
- Java TemporalAdjusters教程
- Apache FileUtils教程
- Java Stream 過濾器
- Java 流歸約
- Java 流映射
- Java InputStreamReader教程
- 在 Java 中讀取文本文件
- Java Unix 時間
- Java LocalTime
- Java 斐波那契
- Java ProcessBuilder教程
- Java 11 的新功能
- ZetCode JavaScript 教程
- Ramda 教程
- Lodash 教程
- Collect.js 教程
- Node.js 簡介
- Node HTTP 教程
- Node-config 教程
- Dotenv 教程
- Joi 教程
- Liquid.js 教程
- faker.js 教程
- Handsontable 教程
- PouchDB 教程
- Cheerio 教程
- Axios 教程
- Jest 教程
- JavaScript 正則表達式
- 用 JavaScript 創建對象
- Big.js 教程
- Moment.js 教程
- Day.js 教程
- JavaScript Mustache 教程
- Knex.js 教程
- MongoDB JavaScript 教程
- Sequelize 教程
- Bookshelf.js 教程
- Node Postgres 教程
- Node Sass 教程
- Document.querySelector教程
- Document.all教程
- JSON 服務器教程
- JavaScript 貪食蛇教程
- JavaScript 構建器模式教程
- JavaScript 數組
- XMLHttpRequest教程
- 從 JavaScript 中的 URL 讀取 JSON
- 在 JavaScript 中循環遍歷 JSON 數組
- jQuery 教程
- Google 圖表教程
- ZetCode Kotlin 教程
- Kotlin Hello World 教程
- Kotlin 變量
- Kotlin 的運算符
- Kotlin when表達式
- Kotlin 數組
- Kotlin 范圍
- Kotlin Snake
- Kotlin Swing 教程
- Kotlin 字符串
- Kotlin 列表
- Kotlin 映射
- Kotlin 集合
- Kotlin 控制流程
- Kotlin 寫入文件
- Kotlin 讀取文件教程
- Kotlin 正則表達式
- ZetCode 其它教程
- TCL 教程
- Tcl
- Tcl 語法結構
- Tcl 中的基本命令
- Tcl 中的表達式
- Tcl 中的控制流
- Tcl 中的字符串
- Tcl 列表
- Tcl 中的數組
- Tcl 中的過程
- 輸入&輸出
- AWK 教程
- Vaadin 教程
- Vaadin 框架介紹
- Vaadin Grid教程
- Vaadin TextArea教程
- Vaadin ComboBox教程
- Vaadin Slider教程
- Vaadin CheckBox教程
- Vaadin Button教程
- Vaadin DateField教程
- Vaadin Link教程
- ZetCode PHP 教程
- PHP 教程
- PHP
- PHP 語法結構
- PHP 基礎
- PHP 數據類型
- PHP 字符串
- PHP 運算符
- PHP 中的控制流
- PHP 數組
- PHP 數組函數
- PHP 中的函數
- PHP 正則表達式
- PHP 中的面向對象編程
- PHP 中的面向對象編程 II
- PHP Carbon 教程
- PHP Monolog 教程
- PHP 配置教程
- PHP Faker 教程
- Twig 教程
- Valitron 教程
- Doctrine DBAL QueryBuilder 教程
- PHP Respect 驗證教程
- PHP Rakit 驗證教程
- PHP PDO 教程
- CakePHP 數據庫教程
- PHP SQLite3 教程
- PHP 文件系統函數
- ZetCode Python 教程
- Python 教程
- Python 語言
- 交互式 Python
- Python 語法結構
- Python 數據類型
- Python 字符串
- Python 列表
- Python 字典
- Python 運算符
- Python 關鍵字
- Python 函數
- Python 中的文件
- Python 中的面向對象編程
- Python 模塊
- Python 中的包
- Python 異常
- Python 迭代器和生成器
- Python 內省
- Python Faker 教程
- Python f 字符串教程
- Python bcrypt 教程
- Python 套接字教程
- Python smtplib教程
- OpenPyXL 教程
- Python pathlib教程
- Python YAML 教程
- Python 哈希教程
- Python ConfigParser教程
- Python 日志教程
- Python argparse 教程
- Python SQLite 教程
- Python Cerberus 教程
- Python PostgreSQL 教程
- PyMongo 教程
- PyMySQL 教程
- Peewee 教程
- pyDAL 教程
- pytest 教程
- Bottle 教程
- Python Jinja 教程
- PrettyTable 教程
- BeautifulSoup 教程
- pyquery 教程
- Python for循環
- Python 反轉
- Python Lambda 函數
- Python 集合
- Python 映射
- Python CSV 教程-讀寫 CSV
- Python 正則表達式
- Python SimpleJson 教程
- SymPy 教程
- Pandas 教程
- Matplotlib 教程
- Pillow 教程
- Python FTP 教程
- Python Requests 教程
- Python Arrow 教程
- Python 列表推導式
- Python 魔術方法
- PyQt 中的QPropertyAnimation
- PyQt 中的QNetworkAccessManager
- ZetCode Ruby 教程
- Ruby 教程
- Ruby
- Ruby 語法結構
- Ruby 基礎
- Ruby 變量
- Ruby 中的對象
- Ruby 數據類型
- Ruby 字符串
- Ruby 表達式
- Ruby 控制流
- Ruby 數組
- Ruby 哈希
- Ruby 中的面向對象編程
- Ruby 中的面向對象編程 II
- Ruby 正則表達式
- Ruby 輸入&輸出
- Ruby HTTPClient教程
- Ruby Faraday 教程
- Ruby Net::HTTP教程
- ZetCode Servlet 教程
- 從 Java Servlet 提供純文本
- Java Servlet JSON 教程
- Java Servlet HTTP 標頭
- Java Servlet 復選框教程
- Java servlet 發送圖像教程
- Java Servlet JQuery 列表教程
- Servlet FreeMarker JdbcTemplate 教程-CRUD 操作
- jQuery 自動補全教程
- Java servlet PDF 教程
- servlet 從 WAR 內讀取 CSV 文件
- Java HttpServletMapping
- EasyUI datagrid
- Java Servlet RESTFul 客戶端
- Java Servlet Log4j 教程
- Java Servlet 圖表教程
- Java ServletConfig教程
- Java Servlet 讀取網頁
- 嵌入式 Tomcat
- Java Servlet 分頁
- Java Servlet Weld 教程
- Java Servlet 上傳文件
- Java Servlet 提供 XML
- Java Servlet 教程
- JSTL forEach標簽
- 使用 jsGrid 組件
- ZetCode Spring 教程
- Spring @Bean注解教程
- Spring @Autowired教程
- Spring @GetMapping教程
- Spring @PostMapping教程
- Spring @DeleteMapping教程
- Spring @RequestMapping教程
- Spring @PathVariable教程
- Spring @RequestBody教程
- Spring @RequestHeader教程
- Spring Cookies 教程
- Spring 資源教程
- Spring 重定向教程
- Spring 轉發教程
- Spring ModelAndView教程
- Spring MessageSource教程
- Spring AnnotationConfigApplicationContext
- Spring BeanFactoryPostProcessor教程
- Spring BeanFactory教程
- Spring context:property-placeholder教程
- Spring @PropertySource注解教程
- Spring @ComponentScan教程
- Spring @Configuration教程
- Spring C 命名空間教程
- Spring P 命名空間教程
- Spring bean 引用教程
- Spring @Qualifier注解教程
- Spring ClassPathResource教程
- Spring 原型作用域 bean
- Spring Inject List XML 教程
- Spring 概要文件 XML 教程
- Spring BeanDefinitionBuilder教程
- Spring 單例作用域 bean
- 獨立的 Spring 應用
- 經典 Spring 應用中的JdbcTemplate
- Spring EmbeddedDatabaseBuilder教程
- Spring HikariCP 教程
- Spring Web 應用簡介
- Spring BeanPropertyRowMapper教程
- Spring DefaultServlet教程
- Spring WebSocket 教程
- Spring WebJars 教程
- Spring @MatrixVariable教程
- Spring Jetty 教程
- Spring 自定義 404 錯誤頁面教程
- Spring WebApplicationInitializer教程
- Spring BindingResult教程
- Spring FreeMarker 教程
- Spring Thymeleaf 教程
- Spring ResourceHandlerRegistry教程
- SpringRunner 教程
- Spring MockMvc 教程
- ZetCode Spring Boot 教程
- Spring Boot 發送電子郵件教程
- Spring Boot WebFlux 教程
- Spring Boot ViewControllerRegistry教程
- Spring Boot CommandLineRunner教程
- Spring Boot ApplicationReadyEvent 教程
- Spring Boot CORS 教程
- Spring Boot @Order教程
- Spring Boot @Lazy教程
- Spring Boot Flash 屬性
- Spring Boot CrudRepository 教程
- Spring Boot JpaRepository 教程
- Spring Boot findById 教程
- Spring Boot Data JPA @NamedQuery教程
- Spring Boot Data JPA @Query教程
- Spring Boot Querydsl 教程
- Spring Boot Data JPA 排序教程
- Spring Boot @DataJpaTest教程
- Spring Boot TestEntityManager 教程
- Spring Boot Data JPA 派生的查詢
- Spring Boot Data JPA 查詢示例
- Spring Boot Jersey 教程
- Spring Boot CSV 教程
- SpringBootServletInitializer教程
- 在 Spring Boot 中加載資源
- Spring Boot H2 REST 教程
- Spring Boot RestTemplate
- Spring Boot REST XML 教程
- Spring Boot Moustache 教程
- Spring Boot Thymeleaf 配置
- Spring Boot 自動控制器
- Spring Boot FreeMarker 教程
- Spring Boot Environment
- Spring Boot Swing 集成教程
- 在 Spring Boot 中提供圖像文件
- 在 Spring Boot 中創建 PDF 報告
- Spring Boot 基本注解
- Spring Boot @ResponseBody教程
- Spring Boot @PathVariable教程
- Spring Boot REST Data JPA 教程
- Spring Boot @RequestParam教程
- Spring Boot 列出 bean
- Spring Boot @Bean
- Spring Boot @Qualifier教程
- 在 Spring Boot 中提供靜態內容
- Spring Boot Whitelabel 錯誤
- Spring Boot DataSourceBuilder 教程
- Spring Boot H2 教程
- Spring Boot Web JasperReports 集成
- Spring Boot iText 教程
- Spring Boot cmd JasperReports 集成
- Spring Boot RESTFul 應用
- Spring Boot 第一個 Web 應用
- Spring Boot Groovy CLI
- Spring Boot 上傳文件
- Spring Boot @ExceptionHandler
- Spring Boot @ResponseStatus
- Spring Boot ResponseEntity
- Spring Boot @Controller
- Spring Boot @RestController
- Spring Boot @PostConstruct
- Spring Boot @Component
- Spring Boot @ConfigurationProperties教程
- Spring Boot @Repository
- Spring Boot MongoDB 教程
- Spring Boot MongoDB Reactor 教程
- Spring Boot PostgreSQL 教程
- Spring Boot @ModelAttribute
- Spring Boot 提交表單教程
- Spring Boot Model
- Spring Boot MySQL 教程
- Spring Boot GenericApplicationContext
- SpringApplicationBuilder教程
- Spring Boot Undertow 教程
- Spring Boot 登錄頁面教程
- Spring Boot RouterFunction 教程
- ZetCode Symfony 教程
- Symfony DBAL 教程
- Symfony 表單教程
- Symfony CSRF 教程
- Symfony Vue 教程
- Symfony 簡介
- Symfony 請求教程
- Symfony HttpClient教程
- Symfony Flash 消息
- 在 Symfony 中發送郵件
- Symfony 保留表單值
- Symfony @Route注解教程
- Symfony 創建路由
- Symfony 控制臺命令教程
- Symfony 上傳文件
- Symfony 服務教程
- Symfony 驗證教程
- Symfony 翻譯教程