跳转到内容

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

待办事项
添加截图。



华夏公益教科书