图形用户界面(Graphical User Interface,简称 GUI)编程对于某种语言来说非常重要。Java的应用主要方向是基于Web浏览器的应用,用户界面主要是HTML、CSS和JavaScript等基于Web的技术,这些介绍要到Java EE阶段才能学习到。
而本章介绍的Java图形用户界面技术是基于Java SE 的 Swing,事实上它们在实际应用中使用不多,因此本章的内容只做了解。
AWT是Swing的基础,Swing事件处理和布局管理都是依赖于AWT,AWT内容来自java.awt包,Swing内容来自javax.swing包。AWT和Swing作为图形用户界面技术包括了4个主要的概念:组件(Component)、容器(Container)、事件处理和布局管理器(LayoutManager),下面将围绕这些概念展开。
容器和组件构成了Swing的主要内容,下面分别介绍一下Swing中容器和组件类层次结构。 图所示是Swing容器类层次结构,Swing容器类主要有:JWindow、JFrame和JDialog,其他的不带“J”开头都是AWT提供的类,在Swing中大部分类都是以“J”开头。
Swing容器类层次结构
Swing组件类层次结构
图形界面的组件要响应用户操作,就必须添加事件处理机制。Swing采用AWT的事件处理模型进行事件处理。在事件处理的过程中涉及三个要素:
事件类型和事件监听器接口
事件监听器都是接口,在Java中接口中定义的抽象方法必须全部是实现,哪怕你对某些方法并不关心。为此 Java 还提供了一些与监听器相配套的适配器。监听器是接口,命名采用XXXListener,而适配器是类,命名采用XXX Adapter。在使用时通过继承事件所对应的适配器类,覆盖所需要的方法,无关方法不用实现。
this.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e) {
// 退出系统
System.exit(0);
}
});
可见代码非常的简洁。事件适配器提供了一种简单的实现监听器的手段,可以缩短程序代码。但是,由于Java的单一继承机制,当需要多种监听器或此类已有父类时,就无法采用事件适配器了。
并非所有的监听器接口都有对应的适配器类,一般定义了多个方法的监听器接口,例如WindowListener有多个方法对应多种不同的窗口事件时,才需要配套的适配器,主要的适配器如下:
Java为了实现图形用户界面的跨平台,并实现动态布局等效果,Java 将容器内的所有组件布局交给布局管理器管理。布局管理器负责,如组件的排列顺序、大小、位置,当窗口移动或调整大小后组件如何变化等。
Java SE提供了7种布局管理器包括:FlowLayout、BorderLayout、GridLayout、BoxLayout、CardLayout、SpringLayout 和 GridBagLayout,其中最基础的是 FlowLayout、BorderLayout 和GridLayout 布局管理器。下面重点介绍这三种布局。
主要的构造方法如下:
上述参数align是对齐方式,它是通过FlowLayout的常量指定的,这些常量说明如下:
BorderLayout布局是窗口的默认布局管理器。 BorderLayout 是 JWindow、JFrame 和 JDialog 的默认布局管理器。BorderLayout 布局管理器把容器分成5个区域:North、South、East、West 和 Center,如图所示每个区域只能放置一个组件。
BorderLayout主要的构造方法如下:
BorderLayout 布局有5个区域,为此BorderLayout中定义了5个约束常量,说明如下:
GridLayout布局以网格形式对组件进行摆放,容器被分成大小相等的矩形,一个矩形中放置一个组件。 GridLayout布局主要的构造方法如下:
填充
new Font("TimesRoman", Font.BOLD + Font.ITALIC, 28);
给图形对象或GUI部件设置字体 • 利用Graphics类的setFont()方法确定使用定义的字体 g.setFont(myFont); • 给某个GUI部件设定字体可以使用该部件的setFont()方法。例如: Button btn = new Button("确定"); btn.setFont(myFont); • 使用getFont()方法返回当前的Graphics对象或GUI部件使用的字 体。
颜色处理常用方法 画笔提供了如下方法: • setColor(Color.blue) ---将画笔定为兰色 • getColor( )--获取当前的绘图颜色。
Component类中定义方法 • setBackground(Color.red)----设置组件的背景色为红色 • setForeground(Color.white) ----设置组件的前景色为白色 • getBackground( ) ---获取背景色 • getForeground() ---获取前景色
思考:设置一个红色按钮,上面写黄色字如何实现?
Button btn = new Button("确定");
btn.setBackground(Color.red);
btn.setForeground(Color.yellow);
setXORMode(Color c)
其中,参数c用于指定XOR颜色。3.指定填充图案 • 用setPaint(Paint)方法指定填充方式 以下几个类均实现了Paint接口。 • Color:单色填充。 • GradientPaint:渐变填充。 • TexturePaint:纹理填充。
编写窗体应用,窗体中安排2个按钮,按钮上面的标签分别为“改背景”、“关闭”,点击“改背景”按钮,用随机产生的颜色更改窗体的背景,点击“关闭”按钮可关闭窗体。
采用流式布局 添加按钮 注册监听
package newfile;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test3 {
public static void main(String[] args) {
new MyFrame();
}
static class MyFrame extends Frame {
public MyFrame() {
setTitle("测试");
Button btn = new Button("改背景");
Font f = new Font("黑体", Font.BOLD, 22);
btn.setFont(f);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setBackground(new Color((int)(Math.random() * 0xFFFFFF)));
}
});
setLayout(new FlowLayout());
add(btn);
btn = new Button("关闭");
btn.setFont(f);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
add(btn);
super.setSize(400, 200);
super.setVisible(true);
}
}
}
设有一批英文单词存放在一个数组中,编制一个图形界面程序浏览单词。在界面中安排一个标签显示单词,另有“上一个”、“下一个”两个按钮实现单词的前后翻动。
package newfile;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test3 {
public static void main(String[] args) {
MyFrame myFrame = new MyFrame();
String[] strs = {"welcome", "element", "target", "term", "modify", "yellow"};
myFrame.setContent(strs);
myFrame.setVisible(true);
}
static class MyFrame extends Frame {
private String[] strs;
private int index;
private Label label = new Label();
public MyFrame() {
setSize(400, 200);
setTitle("单词卡片");
Panel panel = new Panel(new FlowLayout());
this.label.setFont(new Font("宋体", Font.PLAIN, 28));
this.label.setAlignment(Label.CENTER);
add("Center", this.label);
add("South", panel);
Button btn = new Button("上一个");
panel.add(btn);
Font f = new Font("黑体", Font.PLAIN, 20);
btn.setFont(f);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
preWord();
}
});
btn = new Button("下一个");
panel.add(btn);
btn.setFont(f);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
nextWord();
}
});
}
public void setContent(String[] strs) {
this.strs = strs;
this.index = 0;
this.label.setText(strs[index]);
}
public void preWord() {
if (this.index <= 0) {
this.index = this.strs.length - 1;
} else {
this.index = --this.index % this.strs.length;
}
this.label.setText(strs[index]);
}
public void nextWord() {
if (index >= 0) {
this.index = ++this.index % this.strs.length;
} else {
this.index = 0;
}
this.label.setText(this.strs[this.index]);
}
}
}