布局管理器 Layout Manager
负责对子空间的布局,当窗口变化的时候,动态调节子控件的位置和大小
代码:
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
public class Demo {
public static void main(String[] args) {
MyFrame frame = new MyFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 600);
frame.setVisible(true);
}
}
class MyFrame extends JFrame{
JLabel a1 = new ColorfulLabel("HelloWorld", Color.YELLOW);
JLabel a2 = new ColorfulLabel("HelloWorld", Color.BLUE);
public MyFrame(String title) {
super(title);
//根容器
Container root = this.getContentPane();
//设置一个自定义的布局器
LayoutManager layout = new SimpleLayout();
root.setLayout(layout);
root.add(a1);
root.add(a2);
}
private class ColorfulLabel extends JLabel{
public ColorfulLabel(String text, Color color) {
this.setText(text);
this.setBackground(color);
this.setOpaque(true);
this.setHorizontalAlignment(SwingConstants.CENTER);
this.setPreferredSize(new Dimension(60, 30));
}
}
private class SimpleLayout implements LayoutManager{
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return null;
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return null;
}
@Override
public void layoutContainer(Container parent) {
int w = parent.getWidth(); //父窗口的宽度 width
int h = parent.getHeight(); //父窗口的高度 height
System.out.println("父容器: " + w + ", " + h);
//a1显示在中间,以Preferred Size作为大小
if(a1.isVisible()) {
//取得该空间所需的显示尺寸
Dimension size = a1.getPreferredSize();
int x = (w - size.width) / 2;
int y = (h - size.height) / 2;
//在设置子控件位置时,其坐标是相对于父窗口的
a1.setBounds(new Rectangle(x, y, size.width, size.height));
}
//a2显示在右上角
if(a2.isVisible()) {
Dimension size = a2.getPreferredSize();
int x = w - size.width;
int y = 0;
a2.setBounds(new Rectangle(x, y, size.width, size.height));
}
}
}
}
布局器的运行机制:
-
给容器设置一个布局器
root.setLayout(layoutMgr) -
当容器大小改变时,自动调用布局器重新布局
layoutMgr.layoutContainer(…) //这个是Swing内部自动调用的!!
要点和细节:
-
Preferred Size,指控件的最佳大小
当调用label.getPreferredSize()时,由它自行测算自己所需的显示尺寸。 -
Dimension 表示尺寸信息
-
普通内部类,静态内部类的区别
手动布局
用创建布局器的方式来进行布局,称为手动布局。
手动布局时,只需重写LayoutManager接口的layoutContainer()方法
但是这个接口有很多其他方法我们不需要实现,每次都要写出来,很麻烦。所以可以设计一个类重写这些方法,我们只需要继承这个类,然后实现我们需要的那个方法即可!!
AfSimpleLayout.java:
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
public abstract class AfSimpleLayout implements LayoutManager{
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return null;
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return null;
}
}
private class SimpleLayout extends AfSimpleLayout{
@Override
public void layoutContainer(Container parent) {
int w = parent.getWidth(); //父窗口的宽度 width
int h = parent.getHeight(); //父窗口的高度 height
System.out.println("父容器: " + w + ", " + h);
//a1显示在中间,以Preferred Size作为大小
if(a1.isVisible()) {
//取得该空间所需的显示尺寸
Dimension size = a1.getPreferredSize();
System.out.println(size.width + " " + size.height);
int x = (w - size.width) / 2;
int y = (h - size.height) / 2;
//在设置子控件位置时,其坐标是相对于父窗口的
a1.setBounds(new Rectangle(x, y, size.width, size.height));
}
//a2显示在右上角
if(a2.isVisible()) {
Dimension size = a2.getPreferredSize();
int x = w - size.width;
int y = 0;
a2.setBounds(new Rectangle(x, y, size.width, size.height));
}
}
}
要点和细节:
- AfSimpleLayout implements了 LayoutManager,但并没有实现LayoutContainer这个方法,所以定义成了抽象方法