Lesson31_GUI&Swing
javaGUI编程
基本概念
- 概念:使用java进行桌面引用程序的开发技术
- GUI:Graphical User Interface图形用户界面,相对一起的命令窗口
javaGUI的几种技术选择
- AWT:java最早的界面库
- Swing:对AWT的扩展,轻量级设计的界面库
- JavaFX:自jdk1.8引入的新的界面库
- SWT:eclipse所使用的界面库,归eclipse管理
第一个GUI程序
import javax.swing.*;
import java.awt.*;
/**
* @Author: 邪灵
* @Date: 2020/11/10 13:34
* @Description: 第一个Swing程序
* @version: 1.0
*/
public class SwingDemo {
private static void createGUI() {
JFrame frame = new JFrame("Swing Demo");//新建窗口
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口就退出程序
Container container = frame.getContentPane();//创建容器
container.setLayout(new FlowLayout());//设置布局为流式布局
container.add(new JLabel("Hello,java"));//添加一个新建的文本
container.add(new JButton("测试"));//添加一个新建的按钮
frame.setSize(400,300);//设置窗口大小
frame.setVisible(true);//窗口是否显示
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createGUI());//参数是线程类,调用createGUI方法
}
}
- Swing项目就是普通的java项目, 使用java.awt.*和java.swing.*下的API,就可以创建窗口程序
继承JFrame
import javax.swing.*;
import java.awt.*;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author: 邪灵
* @Date: 2020/11/3 15:51
* @Description: 创建自定义窗口
* @version: 1.0
*/
public class MyFrame extends JFrame {
public MyFrame(String title) {
super(title);
Container container = getContentPane();//创建容器
container.setLayout(new FlowLayout());//设置布局为流式布局
container.add(new JLabel("Hello,java"));//添加一个新建的文本
container.add(new JButton("测试"));//添加一个新建的按钮
}
}
public class SwingDemo {
private static void createGUI() {
MyFrame frame = new MyFrame("Swing Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,300);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createGUI());
}
}
- 以后对SwingDemo中的代码基本不变,对窗口、控件的方法都是在MyFrame中
Swing与AWT
- Swing是基于awt的,所以在Swing项目中,可以看到会引入java.awt.*下的内容
- 两套控件,使得打头的类
AWT:Label、Button、。。。
Swing:JLabel、JButton、。。。
- Swing是一套轻量化的实现
按钮点击处理
public class MyFrame extends JFrame {
JLabel label = new JLabel("00:00:00");
JButton button = new JButton("显示时间");
public MyFrame(String title) {
super(title);
Container container = getContentPane();//创建容器
container.setLayout(new FlowLayout());//设置布局为流式布局
container.add(label);//添加一个新建的文本
container.add(button);//添加一个新建的按钮
}
public void showTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
label.setText(sdf.format(new Date()));//文本设置内容为当前时间
}
}
public class SwingDemo {
private static void createGUI() {
MyFrame frame = new MyFrame("Swing Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,300);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createGUI());
}
}
- 现在要做的就是点击按钮时调用showTime方法即可
监听器
- 监听器Listener,是Swing里界面事件处理的一种方式。
- 步骤:
- 创建监听器对象listener
- 将监听器对象交给按钮
- 当按钮被点击时,Swing框架会调用监听器里的方法,进行处理
public class MyFrame extends JFrame {
JLabel label = new JLabel("00:00:00");
JButton button = new JButton("显示时间");
public MyFrame(String title) {
super(title);
Container container = getContentPane();//创建容器
container.setLayout(new FlowLayout());//设置布局为流式布局
container.add(label);//添加一个新建的文本
container.add(button);//添加一个新建的按钮
MyButtonListener listener = new MyButtonLestener();//创建监听器对象
button.addActionListener(listener);//将监听器对象交给按钮
}
//创建一个内部类,实现ActionListener接口,即监听器类
private class MyButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//当按钮被点击时,Swing框架会调用监听器的actionPerformed()方法
System.out.println("按钮被点击");
}
}
public void showTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
label.setText(sdf.format(new Date()));//文本设置内容为当前时间
}
}
- 事件处理
public class MyFrame extends JFrame {
JLabel label = new JLabel("00:00:00");
JButton button = new JButton("显示时间");
public MyFrame(String title) {
super(title);
Container container = getContentPane();//创建容器
container.setLayout(new FlowLayout());//设置布局为流式布局
container.add(label);//添加一个新建的文本
container.add(button);//添加一个新建的按钮
MyButtonListener listener = new MyButtonLestener();//创建监听器对象
button.addActionListener(listener);//将监听器对象交给按钮
}
//创建一个内部类,实现ActionListener接口,即监听器类
private class MyButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//当按钮被点击时,Swing框架会调用监听器的actionPerformed()方法
MyFrame.this.showTime();
}
}
public void showTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
label.setText(sdf.format(new Date()));//文本设置内容为当前时间
}
}
- 匿名内部类实现
public class MyFrame extends JFrame {
JLabel label = new JLabel("00:00:00");
JButton button = new JButton("显示时间");
public MyFrame(String title) {
super(title);
Container container = getContentPane();//创建容器
container.setLayout(new FlowLayout());//设置布局为流式布局
container.add(label);//添加一个新建的文本
container.add(button);//添加一个新建的按钮
button.addActionListener(new ActionListener {
public void actionPerformed(ActionEvent e) {
//当按钮被点击时,Swing框架会调用监听器的actionPerformed()方法
MyFrame.this.showTime();
}
});//将监听器对象交给按钮
}
public void showTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
label.setText(sdf.format(new Date()));//文本设置内容为当前时间
}
}
- Lambda表示式实现
public class MyFrame extends JFrame {
JLabel label = new JLabel("00:00:00");
JButton button = new JButton("显示时间");
public MyFrame(String title) {
super(title);
Container container = getContentPane();//创建容器
container.setLayout(new FlowLayout());//设置布局为流式布局
container.add(label);//添加一个新建的文本
container.add(button);//添加一个新建的按钮
button.addActionListener(e -> showTime());//将监听器对象交给按钮
}
public void showTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
label.setText(sdf.format(new Date()));//文本设置内容为当前时间
}
}
回调
- 回调,Callback,是一个设计上的术语。
- 当我们调用系统的一个方法时,叫Call(调用)
frame.setVisible(true);
label.setText(“HelloWorld”);
- 当我们写一个方法被系统调用时,交Callback(回调)
public void actionPerformed(…)
- 在各种编程语言里,都可以实现回调的设计,在java里,使用interface,即接口的语法
控件
- JFrame代表一个窗口,通过JFrame相关的API就可以创建窗口。
JLabel
- JLabel,用于显示短文本、图标
- setText():设置文本
- setFont():设置字体
- setForeground():设置文本颜色(前景色)
- setToolTipText():设置工具提示
public class MyFrame extends JFrame {
public MyFrame(String title) {
super(title);
JButton button = new JButton("点击开始");
JLabel label = new JLabel("00:00:00");
label.setFont(new Font("微软雅黑",0,14));//设置字体
label.setForeground(new Color(30,235,30));//设置字体颜色
label.setToolTipText("我是提示文字");//设置提示文字,类似HTML中title属性,鼠标悬停提示
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(button);
contentPane.add(label);
}
}
public class SwingDemo {
private static void createGUI() {
MyFrame frame = new MyFrame("Swing Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,300);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createGUI());
}
}
- 其他用法
/**
* @Author: 邪灵
* @Date: 2020/11/17 09:53
* @Description:
* @version: 1.0
*/
public class JLabelDemo extends JFrame {
public JLabelDemo(String title) throws HeadlessException {
super(title);
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
JLabel label1 = new JLabel("1");
JLabel label2 = new JLabel("2");
JLabel label3 = new JLabel("3");
JLabel label4 = new JLabel("4");
//设置背景颜色
label1.setBackground(Color.BLUE);
label2.setBackground(Color.GREEN);
label3.setBackground(Color.RED);
label4.setBackground(Color.YELLOW);
//设置标签非透明,默认透明状态
label1.setOpaque(true);
label2.setOpaque(true);
label3.setOpaque(true);
label4.setOpaque(true);
//设置绝对大小
label1.setPreferredSize(new Dimension(60,30));
label2.setPreferredSize(new Dimension(60,30));
label3.setPreferredSize(new Dimension(60,30));
label4.setPreferredSize(new Dimension(60,30));
//设置文本水平对齐
label1.setHorizontalAlignment(SwingConstants.CENTER);
label2.setHorizontalAlignment(SwingConstants.CENTER);
label3.setHorizontalAlignment(SwingConstants.CENTER);
label4.setHorizontalAlignment(SwingConstants.CENTER);
contentPane.add(label1);
contentPane.add(label2);
contentPane.add(label3);
contentPane.add(label4);
}
public static void main(String[] args) {
JLabelDemo demo = new JLabelDemo("彩色标签");
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.setSize(500,500);
demo.setVisible(true);
}
}
- 优化后代码
/**
* @Author: 邪灵
* @Date: 2020/11/17 09:53
* @Description:
* @version: 1.0
*/
public class JLabelDemo1 extends JFrame {
public JLabelDemo1(String title) throws HeadlessException {
super(title);
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
JLabel label1 = new ColorfulLabel("1",Color.RED);
JLabel label2 = new ColorfulLabel("2",Color.GREEN);
JLabel label3 = new ColorfulLabel("3",Color.BLUE);
JLabel label4 = new ColorfulLabel("4",Color.YELLOW);
contentPane.add(label1);
contentPane.add(label2);
contentPane.add(label3);
contentPane.add(label4);
}
private class ColorfulLabel extends JLabel {
public ColorfulLabel(String text,Color color) {
super(text);//有参构造
setOpaque(true);//设置非透明
setBackground(color);//设置背景色
setPreferredSize(new Dimension(60,30));//设置大小
setHorizontalAlignment(SwingConstants.CENTER);//设置水平对齐为居中
}
}
public static void main(String[] args) {
JLabelDemo1 demo = new JLabelDemo1("彩色标签");
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.setSize(500,500);
demo.setVisible(true);
}
}
JTextField
- JTextField用于单行文本输入
- new JTextField(16);新建对象,16表示列数,用于计算宽度。不是字数限制
- setText()/getText();设置文本/获取文本
- setFont();设置字体
- setEnabled();参数未true或false,表示是否禁用文本框。false禁用
public class MyFrame extends JFrame {
public MyFrame(String title) {
super(title);
JLabel name = new JLabel("姓名");
JTextField field = new JTextField(16);
JButton button1 = new JButton("确认");
contentPane.add(name);
contentPane.add(field);
contentPane.add(button1);
//获取输入框文本,以提示框显示,JOptionPane是提示框。给确认按钮事件,输入后点击确认按钮,提示框显示输入的信息
button1.addActionListener(v -> JOptionPane.showMessageDialog(this,"输入:"+field.getText()));
}
}
public class SwingDemo {
private static void createGUI() {
JFrame frame = new JFrame("Swing Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,300);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createGUI());
}
}
JCheckBox
- JCheckBox,复选框
- isSelected()/setSelected();获取/设置选中状态
- setText();选项文字
- addActionListener();事件,用户选中或取消时触发
public class JCheckBoxDemo extends JFrame {
public JCheckBoxDemo(String title) {
super(title);
//新建复选框
JCheckBox checkBox = new JCheckBox("订阅邮箱号");
//设置复选框初始状态是选中状态
checkBox.setSelected(true);
//新建输入框
JTextField field = new JTextField(12);
//获取面板
Container contentPane = getContentPane();
//设置布局
contentPane.setLayout(new FlowLayout());
//添加控件
contentPane.add(checkBox);
contentPane.add(field);
//复选框添加事件处理,判断如果是选中状态,设置输入框启用
//如果未选中状态,禁用输入框
checkBox.addActionListener(e -> field.setEnabled(checkBox.isSelected()?true:false));
}
}
public class Demo {
private static void createGUI() {
JCheckBoxDemo frame = new JCheckBoxDemo("myFrame");
frame.setSize(400,300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()->createGUI());
}
}
JComboBox
- JComboBox是下拉列表
- JComboBox<String> colorList = new JComboBox<>();创建JComboBox,是一个泛型
- colorList.addItem(T);添加数据项,T是创建时指定的类型参数
- getSelectedIndex();获取选中项的索引
- setSelectedIndex();设置选中项
- remove(index);按索引删除
- getSelectedItem()按数据项访问
- setSelectedItem()按数据项访问
- remove(item)按数据项删除
- addActionListener()事件处理
/**
* @Author: 邪灵
* @Date: 2020/11/10 16:52
* @Description: 下拉列表
* @version: 1.0
*/
public class JComboBoxDemo extends JFrame {
public JComboBoxDemo(String title) {
super(title);
//创建下拉列表
JComboBox<String> comboBox = new JComboBox<>();
//创建文本显示
JLabel label = new JLabel("文本显示颜色");
//添加列表项
comboBox.addItem("红色");
comboBox.addItem("绿色");
comboBox.addItem("蓝色");
//获取面板,添加控件
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(comboBox);
contentPane.add(label);
//添加选中事件处理
comboBox.addActionListener(e->{
Color color = null;
switch ((String)comboBox.getSelectedItem()) {
case "红色":
color = Color.RED;
break;
case "绿色":
color = Color.GREEN;
break;
case "蓝色":
color = Color.BLUE;
break;
default:
color = Color.BLACK;
}
label.setForeground(color);
});
}
}
/**
* @Author: 邪灵
* @Date: 2020/11/3 16:24
* @Description: 测试类
* @version: 1.0
*/
public class Demo {
private static void createGUI() {
JComboBoxDemo frame = new JComboBoxDemo("myFrame");
frame.setSize(400,300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()->createGUI());
}
}
- 列表的每一项的值是传入泛型对象的字符串类型,所以对于传入的对象,可以根据显示的样式重写toString方法
布局器
流布局
- FlowLayout:流布局,最简单的布局方式
- 默认为从左到右依次排列控件,如果排列不下,则到第二行。
- 会根据窗口大小自动调整。如果一行排列不下,可以通过调整窗口放大来实现一行显示
- 有三个构造方法
new FlowLayout():默认方式
new FlowLayout(int align):设置对齐为左右或居中。FlowLayout中有常量
new FlowLayout(int align,int hgap,int vgap):设置对齐方式、横向控件间隔、纵向控件间隔
public JLabelDemo1(String title) throws HeadlessException {
super(title);
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout(FlowLayout.CENTER,15,3));
}
边界布局
- BorderLayout:边界布局
- 把容器分为上、下、左、右、中五个区域
- 在使用时往容器中国添加控件,同时制定区域即可
- setPreferredSize():
-对于上下边界,可以调整高度
-对于左右边界,可以调整宽度
/**
* @Author: 邪灵
* @Date: 2020/11/17 13:14
* @Description: 边界布局
* @version: 1.0
*/
public class BorderLayoutDemo extends JFrame {
public BorderLayoutDemo(String title) throws HeadlessException {
super(title);
Container contentPane = getContentPane();
//设置布局为边界布局
contentPane.setLayout(new BorderLayout());
JLabel label1 = new ColorfulLabel("1",Color.RED);
JLabel label2 = new ColorfulLabel("2",Color.GREEN);
JLabel label3 = new ColorfulLabel("3",Color.BLUE);
JLabel label4 = new ColorfulLabel("4",Color.YELLOW);
JLabel label5 = new ColorfulLabel("5",Color.WHITE);
//添加控件,设置放置的区域为左区域
contentPane.add(label1,BorderLayout.LINE_START);
//添加控件,设置放置的区域为右区域
contentPane.add(label2,BorderLayout.LINE_END);
//添加控件,设置放置的区域为上区域
contentPane.add(label3,BorderLayout.PAGE_START);
//添加控件,设置放置的区域为下区域
contentPane.add(label4,BorderLayout.PAGE_END);
//添加控件,设置放置的区域为中心区域
contentPane.add(label5,BorderLayout.CENTER);
//设置上区域的高度,宽度为0,默认就是100%
label3.setPreferredSize(new Dimension(0,80));
//设置下区域的高度,宽度为0,默认就是100%
label4.setPreferredSize(new Dimension(0,80));
//设置左区域的宽度,高度为0,默认就是100%
label1.setPreferredSize(new Dimension(60,0));
//设置上区域的宽度,高度为0,默认就是100%
label2.setPreferredSize(new Dimension(60,0));
}
private class ColorfulLabel extends JLabel {
public ColorfulLabel(String text,Color color) {
super(text);
setOpaque(true);
setBackground(color);
setPreferredSize(new Dimension(60,30));
setHorizontalAlignment(SwingConstants.CENTER);
}
}
private static void creatGUI() {
BorderLayoutDemo demo = new BorderLayoutDemo("demo");
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.setSize(800,800);
demo.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> creatGUI());
}
}
卡片布局
- CardLayout:卡片布局器
- 犹如叠在一起的卡片,每次只显示一张卡片上的内容
- 使用
pane.setLayout(new CardLayout());
pane.add(c1,"name1");
pane.add(c2,"name2");
- 在添加控件时,关联一个String作为名字,便于后面的控制显示
- 如carLayout.show(pane,“name1”);
/**
* @Author: 邪灵
* @Date: 2020/11/17 13:57
* @Description: 卡片布局
* @version: 1.0
*/
public class CardLayoutDemo extends JFrame {
public CardLayoutDemo(String title) throws HeadlessException {
super(title);
//获取主面板
Container contentPane = getContentPane();
//注面板布局为边界布局
contentPane.setLayout(new BorderLayout());
//创建下拉框控件
JComboBox<String> comboBox = new JComboBox<>();
//添加两个选项
comboBox.addItem("第一个面板");
comboBox.addItem("第二个面板");
//添加下拉框到主面板,指定为上区域
contentPane.add(comboBox,BorderLayout.PAGE_START);
//创建独立面板
JPanel panel = new JPanel();
//添加独立面板到主面板,指定为中间区域
contentPane.add(panel,BorderLayout.CENTER);
//创建卡片布局
CardLayout cardLayout = new CardLayout();
//设置独立面板布局为卡片布局
panel.setLayout(cardLayout);
//创建两个面板
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
//面板一添加控件
panel1.add(new JButton("红"));
panel1.add(new JButton("蓝"));
panel1.add(new JButton("绿"));
//面板二添加控件
panel2.add(new JLabel("输入"));
panel2.add(new JTextField(16));
//将两个面板添加到独立面板中,给一个名字,方便控制显示
panel.add(panel1,"buttons");
panel.add(panel2,"text");
//给下拉框添加事件响应,可以用actionlistener
comboBox.addItemListener(v->{
//获取下拉列表选中项下标
int index = comboBox.getSelectedIndex();
if (index==0) {
//选中第一选项,设置独立面板buttons卡片显示
cardLayout.show(panel,"buttons");
} else {
//选中第二选项,设置独立面板text卡片显示
cardLayout.show(panel,"text");
}
});
}
private static void creatGUI() {
CardLayoutDemo demo = new CardLayoutDemo("text");
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.setVisible(true);
demo.setSize(500,500);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()->creatGUI());
}
}
自定义布局器
窗口布局
- 把上层窗口称为容器(container)
- 窗口里可以有多个子窗口或子控件(component)
- 所谓布局,就是决定每一个子控件显示在什么位置
- 在布局时,每个控件占据一个矩形区域Rectangle
- 先取消布局,再通过setBounds()对子控件手动布局
/**
* @Author: 邪灵
* @Date: 2020/11/17 15:01
* @Description: 自定义布局
* @version: 1.0
*/
public class BoundsDemo extends JFrame {
public BoundsDemo(String title) throws HeadlessException {
super(title);
JLabel label1 = new ColorfulLabel("1",Color.RED);
JLabel label2 = new ColorfulLabel("2",Color.GREEN);
Container contentPane = getContentPane();
//取消默认布局,取消布局后如果没有设置组件显示区域,面板什么都不显示
contentPane.setLayout(null);
//设置组件显示的区域,起始点坐标,宽度、高度
label1.setBounds(new Rectangle(0,0,200,200));
label2.setBounds(new Rectangle(100,100,200,100));
//添加组件
contentPane.add(label1);
contentPane.add(label2);
}
private static class ColorfulLabel extends JLabel {
public ColorfulLabel(String text,Color color) {
super(text);
setBackground(color);
setOpaque(true);
setHorizontalAlignment(SwingConstants.CENTER);
}
}
private static void creatGUI() {
BoundsDemo demo = new BoundsDemo("demo");
demo.setSize(400,300);
demo.setVisible(true);
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()->creatGUI());
}
创建布局器
- 布局器,就是布局管理器。layout manager
- 负责对子控件的布局,当窗口变化的时候,动态调整子控件的位置和大小。比如FlowLayout、BorderLayout