JavaGUI编程笔记
内容来源自B站狂神说Java的课程观看总结
1. 简介
1.1 引言
GUI由于需要jre环境并且界面极不美观而快要被淘汰的技术,核心技术包括 Swing 和 AWT ,但是学习他有以下好处:
- 可以写出自己心中想要的小工具
- 工作时候有极小概率需要维护Swing界面
- 了解MVC,了解监听机制
1.2 GUI介绍
GUI全称图形用户界面,Graphical User Interface
2. AWT
2.1 AWT介绍
AWT全名抽象窗口工具,Abstract Window Tools,包含了很多的类和接口
2.2 AWT包含类的结构
2.3 Frame
2.3.1 概念
Frame是一个顶级窗口
2.3.2 构造方法
public Frame(String title):传递一个标题,构造一个Frame对象,标题显示在最上边(最大最小化的那一行)
2.3.3 成员方法
void setVisible(boolean b):设置可见性,true为可见
void setSize(int width, int height):设置框的宽高,单位为像素
void setLocation(int x, int y):设置窗口的弹出位置,单位为像素
void setBackground(Color bgColor):设置背景颜色,Color中有内置颜色,或者直接new一个自定的RGB/RGBa颜色
void setBounds(int x, int y, int width, int height):一步设置宽高即弹出位置
void setResizable(boolean resizable):resizable为false时,设置宽高为不可拖拽
void addWindowListener(WindowAdapter l):绑定关闭按钮的退出功能,这里的退出用到了System.exit(0);
void setLayout(LayoutManager mgr):设置布局方式
2.4 三种布局管理方式
- 流式布局:一行摆满了再去下一行,FlowLayout,以button按钮为例:
Frame frame1 = new Frame("left");
Frame frame2 = new Frame("right");
Frame frame3 = new Frame("center");
frame1.setSize(300,150);frame3.setSize(300,150);frame2.setSize(300,150);
Button b1 = new Button("left");
Button b2 = new Button("right");
Button b3 = new Button("center");
frame1.setLayout(new FlowLayout(FlowLayout.LEFT));
frame2.setLayout(new FlowLayout(FlowLayout.RIGHT));
frame3.setLayout(new FlowLayout(FlowLayout.CENTER));
frame1.add(b1);frame2.add(b2);frame3.add(b3);
frame1.setVisible(true);frame2.setVisible(true);frame3.setVisible(true);
运行效果如下:
- 东西南北中布局:也就是占据东南西北和中间五个方向,以button按钮为例:
Frame frame = new Frame("哈哈哈哈哈哈");
frame.setSize(300,300);
Button b1 = new Button("east");
Button b2 = new Button("west");
Button b3 = new Button("south");
Button b4 = new Button("north");
Button b5 = new Button("center");
frame.add(b1, BorderLayout.EAST);
frame.add(b2, BorderLayout.WEST);
frame.add(b3, BorderLayout.SOUTH);
frame.add(b4, BorderLayout.NORTH);
frame.add(b5, BorderLayout.CENTER);
frame.setVisible(true);
运行效果如下:
-
表格布局:GridLayout,顾名思义,用表格的方式去布局成n行n列的样式,以button按钮为例:
Frame frame = new Frame("乌拉"); frame.setSize(300,300); Button b1 = new Button("btn1"); Button b2 = new Button("btn2"); Button b3 = new Button("btn3"); Button b4 = new Button("btn4"); Button b5 = new Button("btn5"); Button b6 = new Button("btn6"); frame.setLayout(new GridLayout(2,3)); frame.add(b1);frame.add(b2);frame.add(b3); frame.add(b4);frame.add(b5);frame.add(b6); frame.setVisible(true);
运行效果如下:
- 绝对布局:也就是设置布局的时候直接传递一个null,这个类型的布局方式是定死的,每个元素都定制在了固定的位置,位置写死
2.5 Panel
2.5.1 概念
可以将其看做是一个容器,但是不能够单独存在,Panel需要被add进某个框或者某个窗口中,是各类基本组件的载体。具有和Frame基本相同的API
2.6 事件监听
通过以下代码可以为按钮或某个组件绑定监听事件:
button1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("aaaa");
}
});
其中对于ActionEvent类型的对象e,是可以实现多个按钮绑定同一个监听器的关键。可以通过对其设置按钮的信息,来让监听器通过不同的按钮信息判断,主要涉及以下两个方法:
void setActionCommand(String command):设置按钮信息
String getActionCommand():获取按钮信息
2.7 输入框TextField监听
2.7.1 概念
TextField与TextArea的区别是前者只能输入一行文本,而后者可以输入多行文本
2.7.2 使用
- 创建一个TextField对象之后,需要为其绑定监听事件addActionListener(ActionListener l)
- 该方法需要重写void actionPerformed(ActionEvent e)方法,其中这个ActionEvent对象可以有一个返回资源的方法:Object getSource(),监听的是什么对象,那么返回的就是什么类型的对象,直接对Object直接转型即可
- 得到了一个返回的TextField对象之后,可以使用getText()得到文本框中输入的内容,这样就完成了TextField的监听,每一次按下回车都会触发这个输入框的监听事件
2.7.3 其他常用API
void setEchoChar(char c):设置替换编码,输入密码常见的'*',后台获得的值是正常值而不是一串'*'
void setText(String t):设置文本框的内容,通常配合每一次的回车来触发,传递""清空TextField
2.8 画笔
2.8.1 概念
重写Frame中的paint(Graphics g)方法,这个方法不需要调用即可触发,具体步骤想象画图工具中画笔的一般使用步骤:
设置颜色 —> 设置粗细 —> 画东西
2.8.2 Graphics的API
上文提到的paint()方法中传递的Graphics类提供了很多画图形的方法:
void setColor(Color c):设置画笔的颜色
void drawXxxx(...):绘制某些图形线条
void fillXxxx(...):绘制某些实心的填充tuxing
- 养成习惯,画笔使用完毕之后将其还原成最初的颜色:黑色
2.9 鼠标监听事件
实现监听鼠标并且绘制图像,我们可以将其分为以下步骤:
定义一个集合去装鼠标点击过的点
添加鼠标监听事件,并且设置一些可见性等常规设置
根据需求重写MouseAdapter接口中的方法,方法中将鼠标获取的点放进集合中存储
在paint方法中通过遍历集合去绘画鼠标点击过的点
由于paint方法只会执行一次,因此需要在鼠标监听器中通过Frame调用repaint()方法多次去绘制
具体代码如下:
public class SimpleMousePaint {
public static void main(String[] args) {
new MyMousePaint("鼠标监听画图");
}
}
class MyMousePaint extends Frame{
private List<Point> points;//定义一个集合去装鼠标点击过的点
public MyMousePaint(String title){
super(title);
points = new ArrayList<>();
setVisible(true);
setSize(600,600);
addMouseListener(new MyMouseListener());//添加鼠标监听事件
CloseUtils.close(this);//使用我自己写的工具类绑定关闭按钮
}
@Override//重写画图方法
public void paint(Graphics g) {
//遍历集合points,获取鼠标的点
for (Point point : points) {
g.setColor(Color.BLUE);//设置画笔颜色
g.fillOval(point.x, point.y,5, 5); //根据点击的位置绘制5px*5px的小点
}
}
//以适配器模式书写鼠标的监听器内部类
private class MyMouseListener extends MouseAdapter {
//根据需求重写方法,这里重写的是监听鼠标的按压操作
@Override
public void mousePressed(MouseEvent e) {
MyMousePaint myMousePaint = (MyMousePaint) e.getSource();//返回一个监听器调用者的对象
myMousePaint.points.add(new Point(e.getX(), e.getY()));//将鼠标获取的点放进集合中
myMousePaint.repaint();//每次点击鼠标都需要重新跟踪绘制
}
}
}
- 注意!在这一部分如果不通过集合而是通过单个的Point对象,那么之前绘制的点将会丢失,其原理比较笨重:每一次点击将从头将所有的点重新绘制一遍。想要升级该方法,需要更高级的知识。
以上代码的运行结果如下:
2.10 窗口监听事件
WindowListener接口是窗口监听的接口,但是由于接口本身的特质是既然implements了就必须全部实现,于是产生了适配器设计模式,产生了WindowAdapter实现类对其他方法做了空实现,我们只需要书写我们需要的那个方法就可以了,于是直接extends WindowAdapter即可
这里记录比较常用的两个窗口监听状态:
public class MyWindowListener extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("这个方法是在调用该监听器的Frame关闭的时候会触发执行的监听器");
}
@Override
public void windowActivated(WindowEvent e) {
System.out.println("这个方法是在调用该监听器的Frame被激活时触发的监听器");
System.out.println("所谓的被激活其实指的就是鼠标在窗口外点一下,进入未被激活状态,之后又在窗口内点一下,就叫被激活状态");
}
}
2.11 键盘监听事件
实现键盘按键监听以让用户按下对应键的同时做出相应的应答。可以通过如下代码去绑定监听器,做出应答
frame.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP){
System.out.println("您按下了 上");
}
}
});
KeyEvent是一个包含了键盘所有按键(104个)的类,可以通过常量去访问到
3. Swing
一般会使用Swing去开发窗口和面板,因为其升级了AWT比较老式的界面。同时Swing需要获取一个容器,通过容器Container去操作
3.1 窗口JFrame
Swing中的窗口其实和AWT中的类似,只不过是对其做了升级改进,添加了更加人性化的方法。Swing中的Frame叫做JFrame,同样是一个顶级窗口,JFrame比较突出的一个特点就是不需要再去绑定监听事件去关闭窗口了,直接给我们一个方法:
void setDefaultCloseOperation(WindowConstants.常量):传入一个WindowConstants类型的常量去决定关闭的方式
WindowConstants的常量包括有:
public static final int DO_NOTHING_ON_CLOSE = 0;//什么也不做
public static final int HIDE_ON_CLOSE = 1;//隐藏窗口,但是不关闭
public static final int DISPOSE_ON_CLOSE = 2;//等待JVM关闭才关闭(不常用)
public static final int EXIT_ON_CLOSE = 3;//退出并关闭(最常用)
Swing中基本所有的组件都是在AWT的基础上增加一个J,例如JFrame、JLabel等
对于JLabel对象,有一个设置水平对其的方法:
void setHorizontalAlignment(int alignment):设置文本水平位置,alignment可以通过常量SwingConstants.CENTER等去调用
3.2 容器Container
Swing中,放东西都需要一个容器,而不再是简单的放置在Frame中,因此 JFrame 类为我们提供了一个方法返回容器对象:
Container getContentPane():返回容器对象
3.3 弹窗JDialog
弹窗需要明白的一个最重要的概念:弹窗也是一个窗口,是通过另外一个窗口调出的
Swing中使用JDialog用来被弹出,默认就存在关闭方法,请勿自己写,否则报错
public class JDialogDemo1 extends JDialog{
public JDialogDemo1() {
setVisible(true);
add(new JLabel("你好,我是弹窗"));
}
}
class MyJFrameDemo1 extends JFrame{
public void init(){
new JFrame("弹窗测试 ");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//绑定关闭操作
setVisible(true);
setBounds(100,100,600,400);
Container container = getContentPane();
JButton button = new JButton("点击这里有弹窗");
container.add(button);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//弹出弹窗
new JDialogDemo1();
}
});
}
public static void main(String[] args) {
new MyJFrameDemo1().init();
}
}
3.4 标签Icon
Swing为我们提供了Icon接口,该接口中分别定义了三个常用的方法:
void paintIcon(Component c, Graphics g, int x, int y);//绘制图标
int getIconWidth();//获取图标的宽
int getIconHeight();//获取图标的高
icon可以存放在Label、Button等组件中
3.4.1 绘制图标Icon
以将Icon放在Label中为例:
-
书写一个类JLabelDemo1实现Icon接口以及重写接口中的方法,其中void paintIcon(Component c, Graphics g, int x, int y)书写图标的绘制代码
-
通过JLabel的构造方法去将实现类JLabelDemo1的对象放进去,第三个参数是对齐方式
JLabel label = new JLabel("IconTest", new JLabelDemo1(15,15), SwingConstants.CENTER);
-
获取容器对象Container将Label装进去,并且设置可见性即可
3.4.2 绘制图片Icon
以将Icon放在Label中为例,步骤如下:
-
创建一个Label对象,用来装icon对象
-
通过class.getResource(“icon文件名”)的方式获取URL路径
-
创建图片Icon对象,传递url:
ImageIcon icon = new ImageIcon(url);
-
获取容器对象Container将Label装进去
Container container = getContentPane();
container.add(label);
3.5 面板JPanel
JPanel面板和普通的Panel面板类似。
3.5.1 文本域配合滚动条
JTextArea area = new JTextArea(行数,列数);//设置文本域
JScrollPane jScrollPane = new JScrollPane(area);//为文本域添加滑动条
3.6 按钮JButton
提醒:按钮有时候点击之后会出现一直吸引焦点的情况,这个时候需要调用requestFoucs()方法去释放焦点,将焦点还回去
3.6.1 按钮扩展
void setToolTipText(String text):设置按钮提示,鼠标悬浮显示
3.6.2 图片按钮
ImageIcon imageIcon = new ImageIcon(JButtonDemo1.class.getResource("image.jpg"));//获取图片Icon
JButton button = new JButton(imageIcon);//设置按钮
3.6.3 单选按钮JRadioButton
public class JRadioButtonDemo1 extends JFrame {
public void init(){
Container container = getContentPane();
//创建三个单选框
JRadioButton radioButton1 = new JRadioButton("选项一");
JRadioButton radioButton2 = new JRadioButton("选项二");
JRadioButton radioButton3 = new JRadioButton("选项三");
//创建一个单选组,这个组中只能被选中一个
ButtonGroup group = new ButtonGroup();
//将三个单选按钮添加到组中
group.add(radioButton1);group.add(radioButton2);group.add(radioButton3);
//设置一下容器的布局
setLayout(new FlowLayout(FlowLayout.LEFT));
//将三个单选按钮添加进容器
container.add(radioButton1);container.add(radioButton2);container.add(radioButton3);
setVisible(true);
setBounds(100,100,600,100);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JRadioButtonDemo1().init();
}
}
运行结果:
3.6.4 多选按钮 JCheckBox
public class JCheckboxDemo1 extends JFrame {
public void init(){
Container container = getContentPane();
//创建两个复选框按钮
JCheckBox checkBox1 = new JCheckBox("复选框一");
JCheckBox checkBox2 = new JCheckBox("复选框二");
//将两个复选框添加进容器
container.add(checkBox1);
container.add(checkBox2);
setLayout(new FlowLayout(FlowLayout.LEFT));
setVisible(true);
setBounds(100,100,600,100);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JCheckboxDemo1().init();
}
}
运行结果:
3.7 列表
3.7.1 下拉框JComboBox
public class JComboBoxDemo1 extends JFrame {
public void init(){
Container container = getContentPane();
JComboBox comboBox = new JComboBox();//泛型可以直接去掉
comboBox.addItem("--请选择--");
comboBox.addItem("冬瓜");comboBox.addItem("西瓜");comboBox.addItem("南瓜");
container.add(comboBox);
setVisible(true);
setBounds(100,100,600,100);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JComboBoxDemo1().init();
}
}
关于其获取值,可以通过添加监听事件去获取,通过getResource()获得本体,再通过getText()得到文本。
运行结果如下:
3.7.2 列表框
String[] list = {"要钱","要命","要妹子","要抱抱","要黑化"};
JList jList = new JList(list);//泛型可以直接去掉
运行结果如下:
3.8 文本框
3.8.1 普通文本框
JTextField field1 = new JTextField("默认文本", 列数);
3.8.2 密码框
JPasswordField passwordField = new JPasswordField();
passwordField.setEchoChar('*');//可以设置密码的样式,默认为···
3.8.3 文本域
JTextArea textArea = new JTextArea(行数,列数);
3.9 定时器
实现定时器需要实现ActionListener接口,并且创建定时器类Timer
Timer timer = new Timer(int delay, ActionListener listener):delay表示多少毫秒执行一次,listener表示监听对象
通过timer.start();让定时器启动起来