Swing 佈局
外觀
元件的佈局由所使用的佈局管理器決定。Java 內建了 7 個佈局管理器。大多數 UI 是使用它們的某種組合構建的,通常是透過巢狀佈局管理器。最常用的佈局是 FlowLayout、BorderLayout 和 BoxLayout。
LayoutManagers 是 AWT 中的一個概念,它也用於 Swing。這意味著它們可用於渲染基於 AWT 的 UI 以及基於 Swing 的 UI。這裡提到它們是因為它們是 Swing UI 開發的重要組成部分,但它們並不專屬於 Swing。內建的 LayoutManagers 都位於 java.awt 包中。 |
- 用於在中心面板周圍排列元件。
- 調整元件大小以使用其區域的所有可用空間。
- North / South 元件的高度將與其首選高度相同,寬度與其所在元件的寬度相同。
- East / West 元件的寬度將與其首選寬度相同,高度與其所在元件的高度相同,減去 North 和 South 元件的首選高度。
- Center 將使用元件中剩餘的所有空間,在 North / South / East / West 元件的大小確定後。
BorderLayout
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Container;
public class BorderLayoutDemo {
public static void main(String[] args) {
/*
Swing events run in the EventDispatchThread. All swing components
and models must be modified only from the EventDispatchThread.
SwingUtilities.invokeLater(...) and SwingUtilities.invokeAndWait(...)
both will execute a Runnable in the EDT.
*/
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame borderLayoutFrame = new JFrame("Border Layout");
/*
You shouldn't add components directly to a JFrame. As of Java 5 (1.5?)
you're allowed to but it won't be backwards compatible. Add to the
contentPane instead.
*/
Container contentPane = borderLayoutFrame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(new JButton("East Button"), BorderLayout.EAST);
contentPane.add(new JButton("West Button"), BorderLayout.WEST);
contentPane.add(new JButton("North Button"), BorderLayout.NORTH);
contentPane.add(new JButton("South Button"), BorderLayout.SOUTH);
contentPane.add(new JButton("Center"), BorderLayout.CENTER);
borderLayoutFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
borderLayoutFrame.setSize(400, 200);
borderLayoutFrame.setVisible(true);
}
});
}
}
|
- 用於將元件排列成一條直線。
- 如果沒有足夠的空間容納所有元件,它們將被移到下一行。
- 元件設定為其首選大小。
FlowLayout
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
public class FlowLayoutDemo {
public static void main(String[] args) {
/*
Swing events run in the EventDispatchThread. All swing components
and models must be modified only from the EventDispatchThread.
SwingUtilities.invokeLater(...) and SwingUtilities.invokeAndWait(...)
both will execute a Runnable in the EDT.
*/
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame flowLayoutFrame = new JFrame("Flow Layout");
/*
You shouldn't add components directly to a JFrame. As of Java 5 (1.5?)
you're allowed to but it won't be backwards compatible. Add to the
contentPane instead.
*/
Container contentPane = flowLayoutFrame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(new JButton("Button A"));
// buttonB will not be resized smaller than 200x40 pixels
JButton buttonB = new JButton("Button B");
buttonB.setPreferredSize(new Dimension(200, 40));
contentPane.add(buttonB);
contentPane.add(new JButton("Button C"));
contentPane.add(new JButton("Button D"));
flowLayoutFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
flowLayoutFrame.setSize(400, 200);
flowLayoutFrame.setVisible(true);
}
});
}
}
|
- 用於垂直或水平排列元件。
BoxLayout本質上是FlowLayout的替代品,如果這是你想要的功能,它更強大。但是,權力越大,責任越大... 或者類似的東西。擁有更多權力的代價是你必須做更多工作,但你可以讓事物看起來更接近你真正想要的。為了演示,我們將通過幾個例子。
| 雖然關於在 EDT 中執行和新增到內容窗格的註釋不在這些示例中,但請注意,我們仍然在 EDT 中對元件執行所有工作,並將元件新增到內容窗格。 |
BoxLayout 有兩種基本形式:垂直或水平。它們由常量 BoxLayout.X_AXIS、BoxLayout.Y_AXIS、BoxLayout.LINE_AXIS、BoxLayout.PAGE_AXIS 表示。X/Y_AXIS 指定始終沿著容器的 X 軸或 Y 軸佈局元件。然後,元件從左到右 (X_AXIS) 或從上到下 (Y_AXIS) 排列。LINE/PAGE_AXIS 將與 X/Y_AXIS 做完全相同的事情,假設 父容器的 ComponentOrientation 欄位是左到右定向的。如果不是,LINE_AXIS 將從右到左新增元件,而 PAGE_AXIS 預設情況下將在面板的右側對齊元件。如果你打算支援特定於區域設定的佈局,PAGE_AXIS 就是你的選擇。
談論對齊方式很有趣,但讓我們看看一個演示。下面的演示將建立一個主視窗,允許你建立以適當對齊方式佈局的子視窗。
BoxLayout
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class BoxLayoutDemo {
private int alignment;
private ComponentOrientation orientation;
private static final String X_AXIS = "X_AXIS";
private static final String Y_AXIS = "Y_AXIS";
private static final String LINE_AXIS = "LINE_AXIS";
private static final String PAGE_AXIS = "PAGE_AXIS";
private static final String LEFT_TO_RIGHT = "Left to Right";
private static final String RIGHT_TO_LEFT = "Right to Left";
private static final String DEFAULT_ORIENTATION = "Default Orientation";
private ActionListener alignmentListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (X_AXIS.equals(e.getActionCommand())) {
alignment = BoxLayout.X_AXIS;
} else if (Y_AXIS.equals(e.getActionCommand())) {
alignment = BoxLayout.Y_AXIS;
} else if (LINE_AXIS.equals(e.getActionCommand())) {
alignment = BoxLayout.LINE_AXIS;
} else if (PAGE_AXIS.equals(e.getActionCommand())) {
alignment = BoxLayout.PAGE_AXIS;
} else if (LEFT_TO_RIGHT.equals(e.getActionCommand())){
orientation = ComponentOrientation.LEFT_TO_RIGHT;
} else if (RIGHT_TO_LEFT.equals(e.getActionCommand())){
orientation = ComponentOrientation.RIGHT_TO_LEFT;
} else if (DEFAULT_ORIENTATION.equals(e.getActionCommand())){
orientation = null;
}
}
};
public JFrame buildMainFrame(){
JFrame boxLayoutDemoFrame = new JFrame("BoxLayoutFrame");
boxLayoutDemoFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = boxLayoutDemoFrame.getContentPane();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
ButtonGroup alignmentGroup = new ButtonGroup();
JRadioButton xAxisButton = buildAlignmentButton(alignmentGroup, X_AXIS);
xAxisButton.setSelected(true);
JRadioButton yAxisButton = buildAlignmentButton(alignmentGroup, Y_AXIS);
JRadioButton lineAxisButton = buildAlignmentButton(alignmentGroup, LINE_AXIS);
JRadioButton pageAxisButton = buildAlignmentButton(alignmentGroup, PAGE_AXIS);
final ButtonGroup orientationGroup = new ButtonGroup();
JRadioButton defaultOrientation = buildAlignmentButton(orientationGroup, DEFAULT_ORIENTATION);
defaultOrientation.setSelected(true);
JRadioButton leftToRight = buildAlignmentButton(orientationGroup, LEFT_TO_RIGHT);
JRadioButton rightToLeft = buildAlignmentButton(orientationGroup, RIGHT_TO_LEFT);
JButton openFrameButton = new JButton("Build window");
openFrameButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame demoFrame = new JFrame("Demo Frame");
Container contentPane = demoFrame.getContentPane();
contentPane.setLayout(new BoxLayout(contentPane, alignment));
if(orientation != null){
contentPane.setComponentOrientation(orientation);
}
JButton buttonA;
JButton buttonB;
JButton buttonC;
JButton buttonD;
if(alignment == BoxLayout.PAGE_AXIS || alignment == BoxLayout.Y_AXIS){
buttonA = new JButton("Left Aligned");
buttonA.setAlignmentX(JComponent.LEFT_ALIGNMENT);
buttonB = new JButton("Right Aligned");
buttonB.setAlignmentX(JComponent.RIGHT_ALIGNMENT);
buttonC = new JButton("Center Aligned");
buttonC.setAlignmentX(JComponent.CENTER_ALIGNMENT);
buttonD = new JButton("Default Aligned");
} else {
buttonA = new JButton("Top Aligned");
buttonA.setAlignmentY(Component.TOP_ALIGNMENT);
buttonB = new JButton("Bottom Aligned");
buttonB.setAlignmentY(Component.BOTTOM_ALIGNMENT);
buttonC = new JButton("Center Aligned");
buttonC.setAlignmentY(Component.CENTER_ALIGNMENT);
buttonD = new JButton("Default Aligned");
}
contentPane.add(buttonA);
contentPane.add(buttonB);
contentPane.add(buttonC);
contentPane.add(buttonD);
demoFrame.pack();
demoFrame.setVisible(true);
}
});
contentPane.add(new JLabel("Alignment Options"));
contentPane.add(xAxisButton);
contentPane.add(yAxisButton);
contentPane.add(lineAxisButton);
contentPane.add(pageAxisButton);
contentPane.add(new JSeparator());
contentPane.add(new JLabel("Orientation"));
contentPane.add(defaultOrientation);
contentPane.add(leftToRight);
contentPane.add(rightToLeft);
contentPane.add(new JSeparator());
contentPane.add(openFrameButton);
boxLayoutDemoFrame.setSize(250, 300);
return boxLayoutDemoFrame;
}
private JRadioButton buildAlignmentButton(ButtonGroup alignmentGroup, String alignmentName) {
JRadioButton xAxisButton = new JRadioButton(alignmentName, false);
xAxisButton.setActionCommand(alignmentName);
xAxisButton.addActionListener(alignmentListener);
alignmentGroup.add(xAxisButton);
return xAxisButton;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BoxLayoutDemo demo = new BoxLayoutDemo();
JFrame boxLayoutDemoFrame = demo.buildMainFrame();
boxLayoutDemoFrame.setVisible(true);
}
});
}
}
|
- 用於從一組元件中一次顯示一個元件。它就像一副閃卡,你一次只顯示一張卡片,因此得名。你可以隨時快速更改顯示哪個元件,例如,當用戶單擊按鈕時。
- 用於將元件排列在一個均勻間隔的網格中。
GridLayout
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
public class GridLayoutDemo extends JFrame {
private static final long serialVersionUID = 1L;
public GridLayoutDemo() {
/*
* Calls the constructor in superclass.
*/
super("GridLayout Demo");
/*
* Sets the close operation to DISPOSE_ON_CLOSE.
*/
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
/*
* Creates a new GridLayout object. It has 2 rows and any number of
* columns depending of the component count on container. The horizontal
* and vertical gaps are 10 and 15, respectively.
*/
GridLayout layout = new GridLayout(2, 0, 10, 15);
/*
* The default layout manager for the JFrame's content pane is
* BorderLayout. So, we must to change it.
*/
setLayout(layout);
/*
* Just add the new components.
*/
add(new JButton("Button 1"));
add(new JButton("Button 2"));
add(new JLabel("Label 1", SwingConstants.CENTER));
add(new JCheckBox("CheckBox 1"));
add(new JLabel("Label 2", SwingConstants.CENTER));
add(new JLabel("Label 3", SwingConstants.CENTER));
add(new JButton("Button 3"));
/*
* Adjusts the windows size, centers it in screen and makes it visible.
*/
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
/*
* Creates a new instance of GridLayoutDemo. Try to resize the window
* and see the results.
*/
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GridLayoutDemo();
}
});
}
}
|
class GUI
{
JFrame frame;
JButton btn1,btn2,btn3,btn4,btn5;
public void init()
{
frame = new JFrame();
btn1 = new JButton("1");
btn2 = new JButton("2");
btn3 = new JButton("3");
btn4 = new JButton("4");
btn5 = new JButton("5");
frame.setLayout(new GridBagLayout());
GridBagConstraints g = new GridBagConstraints();
g.gridx = 0;
g.gridy = 0;
frame.add(btn1,g);
g.gridx = 1;
g.gridy = 0;
frame.add(btn2,g);
g.gridx = 2;
g.gridy = 0;
frame.add(btn3,g);
g.gridx = 3;
g.gridy = 0;
frame.add(btn4,g);
g.gridx = 4;
g.gridy = 0;
frame.add(btn5,g);
frame.setVisible(true);
frame.setSize(300,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public GUI()
{
init();
}
}
