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();
}
}