【Java-GUI】01 AWT & 布局
https://www.bilibili.com/video/BV1Z54y1S7ns
——1、AWT
完整描述:Abstract Window Toolkit 抽象窗口工具集
提供的API资源
抽象基类:
java.awt.Component
java.awt.MenuComponent
布局接口:
java.awt.LayoutManager
容器组件:
java.awt.Container
——2、Container继承体系
// 子类窗体容器 java.awt.Window // 子类面板容器 java.awt.Panel // 子类滚动条窗格容器 java.awt.ScrollPane
缺省的布局方式:
Window是可以独立存在的顶级窗口,默认使用BorderLayout边界布局
Panel可以嵌入其他组件,默认使用FlowLayout流式布局
ScrollPane是一个带滚动条的容器,和Window一样使用BorderLayout边界布局
常用的方法:
Component组件
// 设置组件在界面中出现的位置 void setLocation(int x, int y) // 设置组件的大小 void setSize(int width, int length) // 等与上面的方法合并在一起 void setBounds(int x, int y, int width, int height) // 设置是否可见(是否出现在界面中) void setVisible(Boolean b)
Container子类
// 向容器中添加组件,返回添加的组件 Component add(Component comp) // 获取指定位置上的组件 Component getComponentAt(int x, int y) // 返回容器内组件的数量 int getComponentCount() // 返回容器内的所有组件 Component[] getComponents()
——3、三大组件
Window演示案例:
package cn.dzz; import java.awt.*; public class Main { public static void main(String[] args) { // 创建一个窗口对象 Frame frame = new Frame("一个空窗口"); // 设置出现的的位置 (像素单位) frame.setLocation(100, 100); // 设置窗口对象的大小 (像素单位) frame.setSize(600, 300); // 设置可见 frame.setVisible(true); } }
Panel演示案例:
panel必须放置于windows中
package cn.dzz; import java.awt.*; public class Main { public static void main(String[] args) { // 创建顶级的window对象 Frame frame = new Frame("Panel案例"); // 创建一个panel对象,该对象不可独立存在,需要放在window对象中 Panel panel = new Panel(); // 向panel对象中添加这些组件 panel.add(new TextField("这是一段演示文本")); // 增加一个文本字段对象,理解为输入框 panel.add(new Button("这是一个演示按钮")); // 增加一个按钮对象 // 把面板对象放入window对象中 frame.add(panel); // 同时设置边界和大小 frame.setBounds(100,100,600,300); // 可见 frame.setVisible(true); } }
按钮字符乱码问题:
使用IDEA编写,文本字符默认设置的是UTF-8
但是我们的Windows操作系统默认采用GBK,而像这种通过接口调用系统组件的,
例如这个按钮对象,设置的中文字符就会出现问题。
ScrollPane案例演示:
package cn.dzz; import java.awt.*; public class Main { public static void main(String[] args) { // 创建顶级的window对象 Frame frame = new Frame("ScrollPane-Demo"); ScrollPane scrollPane = new ScrollPane(); // 要设置始终显示滚条 // ScrollPane scrollPane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); scrollPane.add(new TextField("This is a test text")); scrollPane.add(new Button("This is a test button")); frame.add(scrollPane); // 同时设置边界和大小 frame.setBounds(100,100,600,300); // 可见 frame.setVisible(true); } }
——4、LayoutManager布局管理器接口
// 布局管理器接口 java.awt.LayoutManager | // 栅格布局 和 流式布局 java.awt.GridLayout java.awt.FlowLayout // 布局管理器接口的子接口 java.awt.LayoutManager2 | // 卡片布局 java.awt.CardLayout // 栅格包布局 java.awt.GridBagLayout // 边界布局 java.awt.BorderLayout
——5、布局结构
1、流式布局:
指组件的排版统一向一个方向设置,直到边界,向下从头继续
构造器:
FlowLayout() 默认构造器,默认的布局(垂直 + 水平 间距) FlowLayout(int align) 指定对齐方式,默认垂直水平间距 // 参数使用该类的枚举值 FlowLayout.LEFT // 默认值 FlowLayout.RIGHT FlowLayout.CENTER FlowLayout(int align,int hgap,int vgap) 指定对齐方式和垂直水平间距
案例:
package cn.dzz; import java.awt.*; public class Main { public static void main(String[] args) { // 创建顶级的window对象 Frame frame = new Frame("ScrollPane-Demo"); // 变更布局(设置布局) P1:布局方式 P2:水平间距(horizon) P3:垂直间距 (vertical) // frame.setLayout(new FlowLayout(FlowLayout.LEFT,20,20)); // 左对齐 // frame.setLayout(new FlowLayout(FlowLayout.RIGHT,20,20)); // 右对齐 frame.setLayout(new FlowLayout(FlowLayout.CENTER,20,20)); // 中对齐 // 添加多个按钮 for (int i = 1; i < 101; i++) { frame.add(new Button("button-" + i)); } // 通过pack方法让程序自己设置最佳大小 frame.pack(); // 可见 frame.setVisible(true); } }
2、边界布局:
java.awt.BorderLayout
东—西—南—北—中(上下左右中)
上下 进行 水平调整
左右 进行 垂直调整
中 包括水平和垂直两个调整
构造器:
BorderLayout() BorderLayout(int hgap, int vgap)
案例:
package cn.dzz; import java.awt.*; public class Main { public static void main(String[] args) { // 创建顶级的window对象 Frame frame = new Frame("ScrollPane-Demo"); frame.setLayout(new BorderLayout(30,10)); frame.add(new Button("North-Button"),BorderLayout.NORTH); frame.add(new Button("South-Button"),BorderLayout.SOUTH); frame.add(new Button("East-Button"),BorderLayout.EAST); frame.add(new Button("West-Button"),BorderLayout.WEST); frame.add(new Button("Center-Button"),BorderLayout.CENTER); // 通过pack方法让程序自己设置最佳大小 frame.pack(); // 可见 frame.setVisible(true); } }
效果:
随着窗体的拖动,pack方法会自适应的进行调整
区域冲突问题:
package cn.dzz; import java.awt.*; public class Main { public static void main(String[] args) { // 创建顶级的window对象 Frame frame = new Frame("ScrollPane-Demo"); frame.setLayout(new BorderLayout(30,10)); frame.add(new Button("North-Button"),BorderLayout.NORTH); frame.add(new Button("South-Button"),BorderLayout.SOUTH); frame.add(new Button("East-Button"),BorderLayout.EAST); frame.add(new Button("West-Button"),BorderLayout.WEST); // frame.add(new Button("Center-Button"),BorderLayout.CENTER); // frame.add(new TextField("sample text"),BorderLayout.CENTER); // 不设置边界布局会发现,这个文本字段对象占用的是中心布局,且之前的中心按钮对象被移除了 // 要实现多个组件共存在这个边界布局的某一块中,就需要一个面板对象来存放 Panel panel = new Panel(); frame.add(panel,BorderLayout.CENTER); // 交由面板对象来存放 panel.add(new Button("Center-Button")); panel.add(new TextField("sample text")); // 如果其他区域没有插入任何组件,也就是未使用的状态,窗体将会自动将其他使用的组建将该区域自适应的填充 // 通过pack方法让程序自己设置最佳大小 frame.pack(); // 可见 frame.setVisible(true); } }
3、栅格布局
java.awt.GridLayout
可以理解为将窗体划分为表格来进行布局
构造器
GridLayout(int rows,int cols) 确定总共行与列 GridLayout(int rows,int cols,int hgap, int vgap) 包括水平垂直间距
案例:
package cn.dzz; import java.awt.*; public class Main { public static void main(String[] args) { // 创建顶级的window对象 Frame frame = new Frame("ScrollPane-Demo"); // 对顶级窗体设置边界布局 frame.setLayout(new BorderLayout()); // 计算的输入框放入边界布局的顶部,为了可以塞入更多的其他组件,先放Panel进去 Panel topPanel = new Panel(); // columns 30个字符 topPanel.add(new TextField(30)); // 添加放有输入框的panel frame.add(topPanel,BorderLayout.NORTH); // 创建放计算器按钮的panel Panel buttonPanel = new Panel(); // 按钮需要使用栅格布局 3行5列 水平4垂直4 buttonPanel.setLayout(new GridLayout(3,5,4,4)); for (int i = 0; i < 10; i++) { buttonPanel.add(new Button("" + i)); } buttonPanel.add(new Button("+")); buttonPanel.add(new Button("-")); buttonPanel.add(new Button("*")); buttonPanel.add(new Button("/")); buttonPanel.add(new Button(".")); // 将这个面板对象放入Center位置(默认是放入Center,可以不设置) frame.add(buttonPanel,BorderLayout.CENTER); // 通过pack方法让程序自己设置最佳大小 frame.pack(); // 可见 frame.setVisible(true); } }
效果:
4、栅格包布局
java.awt.GridBagLayout
在栅格布局的基础上支持了格子合并的操作
5、卡片布局
java.awt.CardLayout
以时间方式管理组件,加入的组件是一叠卡片。每次只有最上面的卡片可以使用
构造器:
CardLayout() 默认的卡片管理器布局 CardLayout(int hgap,int vgap) 指定卡片与容器左右边界的间距
方法:
first(Container target) 显示target容器的第一个组件
last(Container target) 显示target容器的最后一个组件
previous(Container target) 显示target容器的上一个组件
next(Container target) 显示target容器的下一个组件
show(Container target,String name) 显示Target容器指定的名字卡片
案例:
package cn.dzz; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Main { public static void main(String[] args) { // 窗体 Frame frame = new Frame(); // 创建一个panel对象用来存放卡片对象 Panel cardPanel = new Panel(); // 卡片布局对象是给这个卡片面板对象设置的 CardLayout cardLayout = new CardLayout(); cardPanel.setLayout(cardLayout); // 创建一个字符串数组 String[] strings = { "Card - 1", "Card - 2", "Card - 3", "Card - 4", "Card - 5", }; // 把卡片加入到卡片面板对象中,卡片(按钮) for (int i = 0; i < strings.length; i++) { cardPanel.add(strings[i], new Button(strings[i])); } // 放入卡片面板组件 frame.add(cardPanel, BorderLayout.CENTER); // 创建一个panel对象用来存放按钮对象 Panel buttonPanel = new Panel(); // 创建翻阅用的按钮 Button firstButton = new Button("first"); Button previousButton = new Button("previous"); Button thirdButton = new Button("third"); Button nextButton = new Button("next"); Button lastButton = new Button("last"); // 监听按钮事件 重写的方法将会监听所有按钮,点击触发的事件将会封装到这个参数e对象中 ActionListener actionListener = new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { String actionCommand = e.getActionCommand(); // getActionCommand() 用来获取触发事件的按钮上的文字 // 打印看看就知道了 System.out.println(actionCommand); // 我们就可以根据按钮的字符来改变卡片的显示 switch (actionCommand) { case "first": cardLayout.first(cardPanel); break; case "previous": cardLayout.previous(cardPanel); break; case "third": cardLayout.show(cardPanel, strings[2]); // 指定面板对象和指定具体的字符串 break; case "next": cardLayout.next(cardPanel); break; case "last": cardLayout.last(cardPanel); break; } } }; // 将需要触发上述事件的按钮都添加这个监听对象 firstButton.addActionListener(actionListener); previousButton.addActionListener(actionListener); thirdButton.addActionListener(actionListener); nextButton.addActionListener(actionListener); lastButton.addActionListener(actionListener); // 将按钮放入按钮面板对象中 buttonPanel.add(firstButton); buttonPanel.add(previousButton); buttonPanel.add(thirdButton); buttonPanel.add(nextButton); buttonPanel.add(lastButton); // 按钮面板对象放入窗体的下面 frame.add(buttonPanel, BorderLayout.SOUTH); // 自适应 frame.pack(); // 可视化 frame.setVisible(true); } }
6、盒子布局
java.awt.BoxLayout
由Swing引入,可以再垂直和水平方向上摆放GUI组件
构造器:
BoxLayout(Constainer target, int axis)
axis参数
BoxLayout.X_AXIS 水平
BoxLayout.Y_AXIS 垂直
案例:
package cn.dzz; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Main { public static void main(String[] args) { // 窗体 Frame frame = new Frame(); // 盒子布局 ,对窗体进行整体的布局 BoxLayout boxLayout = new BoxLayout(frame, BoxLayout.Y_AXIS); // 设置布局 frame.setLayout(boxLayout); // 添加两个按钮 frame.add(new Button("Top-Button")); frame.add(new Button("Down-Button")); // 自适应 frame.pack(); // 可视化 frame.setVisible(true); } }
直接设置窗体为盒子布局太局限了,所以又提供了一个Box对象容器
Box对象默认就是BoxLayout布局,等同于Panel的作用一样
方法:
static Box createHorizontalBox() 创建水平排列的Box容器 static Box createVerticalBox() 创建垂直排列的Box容器
案例:
package cn.dzz; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Main { public static void main(String[] args) { // 窗体 Frame frame = new Frame(); // 创建水平盒子容器 Box hBox = Box.createHorizontalBox(); // 创建垂直盒子容器 Box vBox = Box.createVerticalBox(); // 放入窗体中 frame.add(hBox, BorderLayout.NORTH); frame.add(vBox, BorderLayout.CENTER); // 水平盒子容器添加按钮 Button hButton1 = new Button("h-button-1"); Button hButton2 = new Button("h-button-2"); hBox.add(hButton1); hBox.add(hButton2); // 垂直盒子容器添加按钮 Button vButton1 = new Button("v-button-1"); Button vButton2 = new Button("v-button-2"); vBox.add(vButton1); vBox.add(vButton2); // 自适应 frame.pack(); // 可视化 frame.setVisible(true); } }
创建水平分割和垂直分割的间距对象
static Component createHorizontalGlue() 水平 static Component createVerticalGlue() 垂直
创建指定间距的间距对象
static Component createHorizontalStruct(int width) 固定宽度,高度可拉伸 static Component createVerticalStruct(int height) 固定高度,宽度可拉伸
案例:
package cn.dzz; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Main { public static void main(String[] args) { // 窗体 Frame frame = new Frame(); // 创建水平盒子容器 Box hBox = Box.createHorizontalBox(); // 创建垂直盒子容器 Box vBox = Box.createVerticalBox(); // 放入窗体中 frame.add(hBox, BorderLayout.NORTH); frame.add(vBox, BorderLayout.CENTER); hBox.add(new Button("hButton-1")); // 创建一个分割的间距对象 hBox.add(Box.createHorizontalGlue()); hBox.add(new Button("hButton-2")); // 创建一个指定分割值10的间距对象 hBox.add(Box.createHorizontalStrut(10)); hBox.add(new Button("hButton-3")); // 垂直盒子的设置 vBox.add(new Button("vButton-1")); // 垂直分割建立 vBox.add(Box.createVerticalGlue()); vBox.add(new Button("vButton-2")); // 指定高度的垂直分割 vBox.add(Box.createVerticalStrut(10)); vBox.add(new Button("vButton-3")); // 自适应 frame.pack(); // 可视化 frame.setVisible(true); } }
从运行的结果上可以看出来,当我们拖动窗体调整大小
Glue设置的大小会随着窗体大小的变化而变化
——1、常用组件
java.awt.Button 按钮
java.awt.Canvas 绘图画布
java.awt.Checkbox 复选框
java.awt.CheckboxGroup 复选框组
java.awt.Choice 下拉选择框
java.awt.Frame 窗口
java.awt.Label 标签
java.awt.List 列表框,添加多项条目
java.awt.Pane 不能单独存在基本容器类,必须放到其他容器中
java.awt.Scrollbar 滚动条
java.awt.ScrollPane 滚动条容器
java.awt.TextArea 多行文本域
java.awt.TextField 单行文本框
案例:
package cn.dzz; import javax.swing.*; import java.awt.*; public class Main { public static void main(String[] args) { // 创建窗体 Frame frame = new Frame(); // 创建窗体中的组件,暂时先不设置布局 TextArea textArea = new TextArea(5,20); // 文本框 Choice choice = new Choice(); // 下拉选择框 choice.add("red"); // 添加下拉选项 choice.add("green"); choice.add("yellow"); CheckboxGroup checkboxGroup = new CheckboxGroup(); // 单选的选项组 Checkbox cbxMale = new Checkbox("male", checkboxGroup, true); // 男性女性是一组的,不可多选 Checkbox cbxFemale = new Checkbox("female", checkboxGroup, false); Checkbox cbxIsMarry = new Checkbox("isMarried"); // 是否已婚可选可不选 List list = new List(6,true); // 列表 list.add("red"); list.add("green"); list.add("blue"); TextField textField = new TextField(20); // 文本输入框和按钮 Button btnOk = new Button("ok"); // 确定按钮 // 布局和组装 Box cbxHorizontalBox = Box.createHorizontalBox(); // 下拉和单选一栏组装 cbxHorizontalBox.add(choice); cbxHorizontalBox.add(cbxMale); cbxHorizontalBox.add(cbxFemale); cbxHorizontalBox.add(cbxIsMarry); Box sideVerticalBox = Box.createVerticalBox(); // 上下布局盒子 sideVerticalBox.add(textArea); // 上面是文本框 sideVerticalBox.add(cbxHorizontalBox); // 下面是单选和下拉 Box topHorizontalBox = Box.createHorizontalBox(); // 最后再用一个大盒子左右合并装在一起 topHorizontalBox.add(sideVerticalBox); topHorizontalBox.add(list); frame.add(topHorizontalBox, BorderLayout.CENTER); Box bottomHorizontalBox = Box.createHorizontalBox(); // 底部 bottomHorizontalBox.add(textField); bottomHorizontalBox.add(btnOk); frame.add(bottomHorizontalBox, BorderLayout.SOUTH); // 可见 与 自适应 frame.setVisible(true); frame.pack(); } }
案例效果: