跳轉到內容

Swing 佈局

50% developed
來自華夏公益教科書,開放的書籍,開放的世界


元件的佈局由所使用的佈局管理器決定。Java 內建了 7 個佈局管理器。大多數 UI 是使用它們的某種組合構建的,通常是透過巢狀佈局管理器。最常用的佈局是 FlowLayout、BorderLayout 和 BoxLayout。

Note LayoutManagers 是 AWT 中的一個概念,它也用於 Swing。這意味著它們可用於渲染基於 AWT 的 UI 以及基於 Swing 的 UI。這裡提到它們是因為它們是 Swing UI 開發的重要組成部分,但它們並不專屬於 Swing。內建的 LayoutManagers 都位於 java.awt 包中。

BorderLayout

[編輯 | 編輯原始碼]
  • 用於在中心面板周圍排列元件。
  • 調整元件大小以使用其區域的所有可用空間。
    • North / South 元件的高度將與其首選高度相同,寬度與其所在元件的寬度相同。
    • East / West 元件的寬度將與其首選寬度相同,高度與其所在元件的高度相同,減去 North 和 South 元件的首選高度。
    • Center 將使用元件中剩餘的所有空間,在 North / South / East / West 元件的大小確定後。
Computer code 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

[編輯 | 編輯原始碼]
  • 用於將元件排列成一條直線。
  • 如果沒有足夠的空間容納所有元件,它們將被移到下一行。
  • 元件設定為其首選大小。
Computer code 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

[編輯 | 編輯原始碼]
  • 用於垂直或水平排列元件。BoxLayout 本質上是 FlowLayout 的替代品,如果這是你想要的功能,它更強大。但是,權力越大,責任越大... 或者類似的東西。擁有更多權力的代價是你必須做更多工作,但你可以讓事物看起來更接近你真正想要的。為了演示,我們將通過幾個例子。
Note 雖然關於在 EDT 中執行和新增到內容窗格的註釋不在這些示例中,但請注意,我們仍然在 EDT 中對元件執行所有工作,並將元件新增到內容窗格。

BoxLayout 有兩種基本形式:垂直或水平。它們由常量 BoxLayout.X_AXISBoxLayout.Y_AXISBoxLayout.LINE_AXISBoxLayout.PAGE_AXIS 表示。X/Y_AXIS 指定始終沿著容器的 X 軸或 Y 軸佈局元件。然後,元件從左到右 (X_AXIS) 或從上到下 (Y_AXIS) 排列。LINE/PAGE_AXIS 將與 X/Y_AXIS 做完全相同的事情,假設 父容器的 ComponentOrientation 欄位是左到右定向的。如果不是,LINE_AXIS 將從右到左新增元件,而 PAGE_AXIS 預設情況下將在面板的右側對齊元件。如果你打算支援特定於區域設定的佈局,PAGE_AXIS 就是你的選擇。

談論對齊方式很有趣,但讓我們看看一個演示。下面的演示將建立一個主視窗,允許你建立以適當對齊方式佈局的子視窗。

Computer code 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);
            }
        });
    }
}

CardLayout

[編輯 | 編輯原始碼]
  • 用於從一組元件中一次顯示一個元件。它就像一副閃卡,你一次只顯示一張卡片,因此得名。你可以隨時快速更改顯示哪個元件,例如,當用戶單擊按鈕時。

GridLayout

[編輯 | 編輯原始碼]
  • 用於將元件排列在一個均勻間隔的網格中。
Computer code 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();
            }

        });

    }
}

GridBagLayout

[編輯 | 編輯原始碼]
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();
    }
}

SpringLayout

[編輯 | 編輯原始碼]
Clipboard

待辦事項
完成此部分。



Clipboard

待辦事項
新增截圖。



華夏公益教科書