Java GUI

Java GUI——Java图形用户界面

Java GUI概述

早期,电脑向用户提供的是单调、枯燥、纯字符状态的“命令行界面(CLI),在今天,一个应用软件没有良好的GUI是无法让用户接受的。Java语言提供了一套可以轻松构建GUI的工具

AWT 是 Java最早的界面库(java.awt:Abstract Windows ToolKit(抽象窗口工具包),需要调用本地系统方法来实现功能属重量级控件)

Swing 是对AWT的扩展(javax.swing:在AWT的基础上, 建立的一套图像界面系统,其中提供了更多的组件,而且完全由Java实现。增强了移植性,属轻量级组件。

AWT&Swing

抽象窗口工具包AWT(Abstract Window Toolkit)是java提供的建立图形用户界面GUI的开发包,AWT可用于Java的Applet 和 Application 中。`java.awt`包提供了基本的GUI设计工具

​ Swing 包含了构建图形界面(GUI)的各种组件,如: 窗口、标签、按钮、文本框等。Swing 提供了许多比 AWT 更好的屏幕显示元素,使用纯 Java 实现,能够更好的兼容跨平台运行

​ 为了和 AWT 组件区分,Swing 组件在javax.swing.*包下,类名均以 J 开头,例如: JFrame、JLabel、JButton等

​ 他们都包含三个重要概念:

  • 组件(Component)
  • 容器(Container)
  • 布局管理器(LayoutManager)

基于Swing的Java GUI设计

设计步骤:

  • 引入Swing 包及其它程序包
  • 选择GUI的外观风格L&F(look & feel)
  • 创建并设置顶层容器
  • 创建与添加Swing组件
  • 显示顶层容器,将整个GUI显示出来
  • 增加事件处理

Swing中的Look & Feel

使用UIManager.setLookAndFeel() 方法进行设置。在该方法中可以使用下面几种参数配置风格:

1
2
3
4
5
6
7
8
9
10
UIManager.getCrossPlatformLookAndFeelClassName()
—Java Look & Feel
UIManager.getSystemLookAndFeelClassName()
— 当前平台的Look & Feel
"javax.swing.plaf.metal.MetalLookAndFeel"
— Java Look & Feel
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel"
— Windows Look & Feel
"com.sun.java.swing.plaf.mac.MacLookAndFeel"
— Mac OS Look & Feel

常用容器

  • 组成GUI的组件如按钮、标签等,不能独立使用,必须放在容器内

  • 容器本身也是一个组件,具有组件的所有性质,另外还具有容纳其它组件的功能

  • 所有的组件都可以通过add()方法向容器中添加

  • 在Swing中,常用的三种类型的容器是JFrame、JPanel、JApplet

顶层容器

  • Swing GUI形成 顶层容器-中间层容器-基本组件 的层次包容关系。具有Swing GUI的应用必须至少有一个顶层容器,它提供了所包含组件需要的绘制与事件处理功能。对于多数应用,顶层容器是JFrameJDialogJApplet的实例
  • 中间层容器是由通用容器构成,主要是为了简化组件的布局,常用组件为JPanelJScrollPaneJTabbedPane
  • 基本组件是直接向用户展示信息或获取用户输入的组件

JFram相当于桌子,JPanel相当于桌子上的盘子,JButton相当于盘子里面的菜

Layout Manager

  • 容器中组件的布局通常由Layout Manager控制。
  • Layout Manager负责决定容器的布局策略及容器内组件的排列顺序、大小和位置,以及当窗口移动或调整大小后组件如何变化等。
  • 每个容器都有一个默认的Layout Manager,可通过调用setLayout()方法改变。
  • Java提供的布局管理器(要用的时候自己查):
    • FlowLayout 流式
    • BorderLayout 边界
    • GridLayout 网格
    • CardLayout 卡片
    • GridBagLayout 网格包
    • BoxLayout 箱式

AWT事件处理模型

​ 当用户在界面上利用鼠标或键盘进行操作时,监测GUI的操作系统将所发生的事件传送给GUI应用程序,应用程序根据事件的类型作出相应的反应。基于Swing的GUI中,仍然采用AWT的事件处理模型。下面按如下的顺序介绍:

  • 什么是事件
  • 事件处理机制
  • 事件目录
  • 事件、接口、方法列表
  • 多监听器
  • 事件适配器

什么是事件

  • 事件—描述所发生事件的对象

    Java中有很多不同类型的事件类,用来描述不同类型的用户动作。如按下键盘、拖动或单击鼠标

  • 事件源—产生事件的组件

​ 产生事件的组件就是一个事件源。例如当在一个Button上单击鼠标时,将产生一个ActionEvent事件,这个Button就是事件源

  • 事件处理器—一个接收事件对象并处理用户交互的方法

事件处理机制——委托模型/监听器模型:

事件处理

  • 每类事件有一个相应的监听器接口,定义了接收事件的方法。实现该接口的类,其对象可作为监听器注册
  • 需要响应用户操作的相关组件要注册一个或多个相应事件的监听器,该监听器中包含了能接收和处理事件的事件处理
  • 事件对象只向已注册的监听器报告

委托方式的事件处理机制的实现包括以下两部分:

  1. 在事件处理类的声明中指定要实现的监听器接口,并实现该监听器接口中的所有方法。例如:
1
2
3
4
5
public class MyClass implements ActionListener { 
public void actionPerformed(ActionEvent e) {
...//响应某个动作的代码...
}
}
  1. 在一个或多个组件上将监听器类的实例注册为监听器,如:
1
someComponent.addActionListener(new MyClass( )); 
事件分类:

事件分类

  • 对于AWT每种类型的事件,都定义了相应的事件处理接口,即监听器接口。监听器接口中要定义一个或多个事件处理方法,这些方法在特定事件出现时被调用

  • 实现某种监听器接口的类,其对象可以作为接收并处理相应事件的监听器。

  • 可以使用一个监听器处理多个组件可能产生的多种事件。如:

1
2
public class ComplexListener implements 
MouseMotionListener, MouseListener, ActionListener{ ……
  • 可以在一个组件上注册多个监听器,而且多个监听器可以监听同一个事件

事件适配器

​ 事件适配器(Event Adapter)是一种设计模式的实现,主要用于简化事件监听器接口的实现过程。通常,事件监听器接口会包含多个方法,而有时候我们可能只需要关心并处理某些特定事件,而不是所有事件。直接实现完整的接口可能会导致很多方法需要被无意义地空实现,增加了代码冗余。

​ 事件适配器类则作为抽象类,实现了相应事件监听器接口,并将所有方法默认实现为空方法体。因此,开发者可以直接继承这些适配器类,仅需覆盖自己感兴趣的方法,从而避免了实现接口中所有方法的繁琐工作

既使用Adapter类,又避免多重继承的限制:

​ 在一个类中定义内部类,由内部类继承相应Adapter类。匿名类(Anonymous Class)是没有名字的内部类。可以使用匿名类进行事件处理。

1
2
3
4
5
6
7
8
9
10
public class MyApplet extends Applet { 
...
someObject.addMouseListener(new MyAdapter());
...
class MyAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
...//Event handler implementation goes here...
...
}
}

应用实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MultiListener extends JFrame implements ActionListener {

JTextArea topTextArea;
JTextArea bottomTextArea;
JButton button1, button2;

public MultiListener(String s) {
super(s);

JLabel l = null;
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag); //Frame设置为GridBagLayout布局管理器。

c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
l = new JLabel("监听器听到的:");
gridbag.setConstraints(l, c);
add(l);

c.weighty = 1.0;
topTextArea = new JTextArea(5, 20);
topTextArea.setEditable(false);
gridbag.setConstraints(topTextArea, c);
add(topTextArea);

c.weightx = 0.0;
c.weighty = 0.0;
l = new JLabel("偷听者听到的:");
gridbag.setConstraints(l, c);
add(l);

c.weighty = 1.0;
bottomTextArea = new JTextArea(5, 20);
bottomTextArea.setEditable(false);
gridbag.setConstraints(bottomTextArea, c);
add(bottomTextArea);

c.weightx = 1.0;
c.weighty = 0.0;
c.gridwidth = 1;
c.insets = new Insets(10, 10, 0, 10);
button1 = new JButton("啦 啦 啦");
gridbag.setConstraints(button1, c);
add(button1);

c.gridwidth = GridBagConstraints.REMAINDER;
button2 = new JButton("你别说话!");
gridbag.setConstraints(button2, c);
add(button2);

//当前MultiListener对象同时监听两个Button的事件。
button1.addActionListener(this);
button2.addActionListener(this);

//为第二个Button再注册一个监听器。
button2.addActionListener(new Eavesdropper());

//向窗口注册响应关闭窗口操作的监听器。
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});

pack();
setVisible(true);
}

public void actionPerformed(ActionEvent e) {
topTextArea.append(e.getActionCommand() + "\n");
}

//第二个Button的监听器类。
class Eavesdropper implements ActionListener {
public void actionPerformed(ActionEvent e) {
bottomTextArea.append("OK,"+ e.getActionCommand() + "\n");
}
}

public static void main(String[] args){

MultiListener m=new MultiListener("Multilistener example" );

}
}