AWT组件与Swing组件概述

用户界面设计

java.awt包

-> Abstract Window Toolkit(抽象窗口工具包)

java.awt包中的类创建的组件 -> 重组件(heavyweight components)

  • 当用java.awt包中的Button类创建一个按钮组件时,都有一个相应的本地组件在为它工作
  • 显示组件和处理组件事件,该本地组件称为它的同位体

javax.swing包

  • 提供更加丰富、功能强大的组件 -> Swing组件,其中大部分组件是轻组件(lightweight components)
  • 没有同位体,而是把与显示组件有关的许多工作和处理组件事件的工作交给相应的UI代表来完成。
  • UI代表是用Java语言编写的类,这些类被增加到Java的运行环境中,因此组件的外观不依赖平台,不仅在不同平台上的外观是相同的,而且与重组件相比有更高的性能。

Component - Container

  • JComponent—————- 轻组件
    • JButton
    • JTextField
    • JTextArea
    • JTree
    • JTable
    • JPanel
  • Window——————– 重组件
    • Frame - JFrame
    • Dialog - JDialog

由Component类的子类或间接子类创建的对象 -> 组件
由Container类的子类或间接子类创建的对象 -> 容器

向容器添加组件:add()容器调用此方法将组件添加到该容器中
调用removeAll()方法,移掉容器中的全部组件
调用remove(Component com)方法,移掉容器中参数指定的组件
当容器添加新的组件或移掉组件时,应让容器调用validate()方法,以保证容器中的组件能正确显示
容器本身也是一个组件,因此可以把一个容器添加到另一个容器中,实现容器的嵌套

javax.swing包中有4个最重要的类:JComponent, JFrame, JApplet和JDialog

  • JComponent类的子类都是轻组件,JComponent类是java.awt包中Container类的子类,因此所有轻组件也都是容器
  • JFrame, JApplet, JDialog都是重组件,即它们是有同位体的组件.窗体(JFrame)、小应用程序(Java Applet)、对话框(JDialog)可以和操作系统交互信息。
  • 轻组件必须在容器中绘制自己,习惯上称这些容器为Swing的顶层/底层容器。

JFrame窗体

java.awt包中Frame类的子类 -> javax.swing包中的JFrame类

1
2
3
4
5
6
//JFrame类的常用方法 
JFrame()//创建一个无标题的窗体。
JFrame(String s)//创建一个标题为s的窗体。
public void setBounds(int a, int b, int width, int height)//设置出现在屏幕上时的初始位置为(a, b),即距屏幕左面a个像素、距屏幕上方b个像素;窗体的宽是width,高是height。
public void setSize(int width, int height)//设置窗体的大小,窗体在屏幕出现时默认位置是(0, 0)。
public void setVisible(boolean b)//设置窗体是可见还是不可见,窗体默认是不可见的。

中间容器

JPanel面板

  • 用JPanel创建一个面板,再向这个面板添加组件,然后把这个面板添加到底层容器或其他中间容器中。
  • JPanel面板的默认布局是FlowLayout布局
  • JPanel类构造方法JPanel()构造一个面板容器对象

JScrollPane滚动窗格

可把一个组件放到一个滚动窗格中,然后通过滚动条来观察这个组件
example:
JTextArea不自带滚动条,如果要把文本区放到一个滚动窗格中,可使用JScrollPane的构造方法JScrollPane(component com)构造一个滚动窗格.

JSplitPane拆分窗格

水平拆分窗格用一条拆分线把容器分成左右两部分,左面放一个组件,右面放一个组件,拆分线可以水平移动。
垂直拆分窗格由一条拆分线分成上下两部分,上面放一个组件,下面放一个组件,拆分线可以垂直移动。

  • JSplitPane的构造方法JSplitPane(int a, Component b, Component c)构造一个拆分窗格.
  • 参数a取JSplitPane的静态常量HORIZONTAL_SPLITVERTICAL_SPLIT,以决定是水平拆分还是垂直拆
    分,后两个参数决定要放置的组件。
  • 拆分窗格调用setDividerLocation(double position)设置拆分线的位置。

JLayeredPane分层窗格

处理重叠问题

  • JLayeredPane容器将容器分为5层,容器使用add(JComponent com, int layer)添加组件com,并指定com所在的层.
  • 其中参数layer取值JLayeredPane类中的类常量:DEFAULT_LAYERPALETTE_LAYERMODAL_LAYERPOPUP_LAYERDRAG_LAYER
  • DEFAULT_LAYER最底层,如果和其它层的组件发生重叠,将被其它组件遮挡
  • DRAG_LAYER层是最上面的层。如果JLayeredPane中添加了许多组件,当你用鼠标移动一组件时,可以把移动的组件放到DRAG_LAYER层,这样,组件在移动过程中,不会被其它组件遮挡。
  • 添加到同一层上的组件,如果发生重叠,后添加的会遮挡先前添加的组件
  • JLayeredPane对象调用public void setLayer(Component com, int layer)可以重新设置组件com所在的层.- 调用public int getLayer(Component com)可以获取组件com所在的层数。
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
import javax.swing.*;
import java.awt.*;

class WindowLayered extends JFrame
{
WindowLayered()
{
// ---
setBounds(100,100,300,300); //设置窗口的初始位置和大小
setVisible(true); //设置窗体是可见/不可见,窗体默认是不可见的。

// --- //创建五个按钮组件,每个按钮代表不同的分层
JButton b1 = new JButton("DEFAULT_LAYER");// 默认层
JButton b2 = new JButton("PALETTE_LAYER");// 调色板层
JButton b3 = new JButton("MODAL_LAYER");// 模式层
JButton b4 = new JButton("POPUP_LAYER");// 弹出层
JButton b5 = new JButton("DRAG_LAYER");// 拖动层

// --- //设置每个按钮组件在窗口中的初始位置和大小
b5.setBounds(50,50,200,100);
b4.setBounds(40,40,200,100);
b3.setBounds(30,30,200,100);
b2.setBounds(20,20,200,100);
b1.setBounds(10,10,200,100);

// --- //创建一个JLayeredPane面板容器对象,用于支持分层布局
JLayeredPane pane = new JLayeredPane();
pane.setLayout(null); //使用绝对布局,因为我们将手动设置组件的位置和大小

// --- //添加组件com,并指定com所在的层.
pane.add(b5,JLayeredPane.DRAG_LAYER);
pane.add(b4,JLayeredPane.POPUP_LAYER);
pane.add(b3,JLayeredPane.MODAL_LAYER);
pane.add(b2,JLayeredPane.PALETTE_LAYER);
pane.add(b1,JLayeredPane.DEFAULT_LAYER);

// --- //将分层窗格添加到窗口的内容面板中,并指定它占据中心位置
add(pane, BorderLayout.CENTER);

// --- //验证窗口的布局,确保所有添加的组件都被正确显示
validate();

// --- //设置窗口关闭时的默认操作,这里设置为关闭时释放窗口资源
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}

public class demo {
public static void main(String args[])
{
new WindowLayered();
}
}

对话框

JDialog类

对话框必须要依赖于某个窗口或组件,当它所依赖的窗口或组件消失时,对话框也将消失;而当它所依赖的窗口或组件可见时,对话框又会自动恢复。

对话框的模式

对话框分为无模式(modaless)有模式(modal)两种。

  • 无模式对话框处于激活状态时,程序仍能激活它所依赖的窗口或组件,它也不堵塞线程的执行。
  • 有模式对话框处于激活状态时,只让程序响应对话框内部的事件,程序不能再激活它所依赖的窗口或组件,而且它将堵塞当前线程的执行,直到该对话框消失不可见。
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.event.*;//导入必要的Java AWT事件处理类
import java.awt.*;//导入Java AWT包,用于图形界面设计
import javax.swing.*;//导入Java Swing包,用于更高级的图形界面组件

// 定义一个继承自JDialog的类MyDialog,并实现ActionListener接口以处理事件
class MyDialog extends JDialog implements ActionListener
{
//定义三个常量,分别代表用户点击Yes按钮、No按钮和关闭窗口的操作
static final int YES=1, NO=0, CLOSE=-1;
int message=10;//存储用户的选择或操作
Button yes,no; //两个按钮对象yes和no

//构造函数,接收JFrame对象作为父窗口,字符串作为标题,布尔值表示是否为模态对话框
MyDialog(JFrame f, String s, boolean b)
{
super(f,s,b); //调用父类JDialog的构造函数

setLayout(new FlowLayout());//设置对话框的布局管理器为FlowLayout
setBounds(60,60,100,100);//设置对话框的位置和大小

//创建Yes按钮,并为其添加事件监听器
yes = new Button("Yes");
yes.addActionListener(this);//this指的是当前MyDialog对象,它实现了ActionListener接口
//创建No按钮,并为其添加事件监听器
no = new Button("No");
no.addActionListener(this);

//将Yes、No按钮添加到对话框中
add(yes);
add(no);

//添加WindowListener的匿名子类,用于处理窗口关闭事件
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
message = CLOSE;
setVisible(false);
}
});
}

//实现ActionListener接口的actionPerformed方法,用于处理按钮点击事件
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==yes) //如果事件源是Yes按钮
{
message = YES;
setVisible(false); //隐藏对话框
}
else if(e.getSource()==no) //如果事件源是No按钮
{
message = NO;
setVisible(false); //隐藏对话框
}
}

//定义getMessage方法,返回用户的操作结果
public int getMessage()
{
return message;
}
}

public class demo1 {
public static void main(String args[])
{
//创建MyDialog对象,父窗口为null(即没有父窗口),标题为"我有模式",为模态对话框
MyDialog dialog = new MyDialog(null, "我有模式", true);

dialog.setVisible(true);//设置对话框为可见

if(dialog.getMessage() == MyDialog.YES)
{
System.out.println("你单击了对话框的yes按钮");
}
if(dialog.getMessage() == MyDialog.NO)
{
System.out.println("你单击了对话框的No按钮");
}
else
{
if(dialog.getMessage() == MyDialog.CLOSE)
{
System.out.println("你单击了对话框的关闭图标");
}
}
System.exit(0); //退出程序
}
}

输入对话框

javax.swing包中的JOptionPane类的静态方法public static String showInputDialog(Component parentComponent, Object message, String title, int messageType)可以创建一个输入对话框.
参数分别是对话框所依赖的组件、对话框上显示的消息、对话框的标题和对话框的外观。

消息对话框

javax.swing包中的JOptionPane类的静态方法public static void showMessageDialog(Component parentComponent, String message, String title, int messageType)可以创建一个消息对话框。
参数分别是对话框所依赖的组件、对话框上显示的消息、对话框的标题和对话框的外观。

确认对话框

确认对话框是有模式对话框,可以用javax.swing包中的JOptionPane类的静态方法public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType)创建一个确认对话框。
参数分别是对话框所依赖的组件、对话框上显示的消息、对话框的标题和对话框的外观。

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
import java.awt.event.*;    //导入AWT事件处理相关的包
import java.awt.*; //导入AWT相关的包
import javax.swing.*; //导入Swing相关的包
import java.util.regex.*; //导入正则表达式相关的包

// 定义一个继承自JFrame并实现ActionListener接口的窗口类
class Dwindow extends JFrame implements ActionListener
{
JButton inputNumber;// 定义一个按钮,用于触发输入对话框
JTextArea save; // 定义一个文本区域,用于显示输入的数字字符序
Pattern p; //模式对象,匹配非数字字符
Matcher m; //匹配对象

Dwindow() // 构造函数,初始化窗口
{
//创建按钮,标签为"单击按钮打开输入对话框",并为其添加动作监听器
inputNumber = new JButton("单击按钮打开输入对话框");
inputNumber.addActionListener(this);
add(inputNumber, BorderLayout.NORTH); //将按钮添加到窗口的北部区域

//创建文本区域,设置行数和列数,用于显示输入的内容
save = new JTextArea(12,16);
add(new JScrollPane(save), BorderLayout.CENTER);//将文本区域放入滚动面板中,并添加到窗口的中心区域

setBounds(60,60,300,300);// 设置窗口的初始位置和大小
setVisible(true);// 设置窗口为可见

//编译正则表达式,匹配一个或多个非数字字符
p = Pattern.compile("\\D+"); //创建模式对象(含有非数字字符的模式)

//设置窗口关闭操作,当用户关闭窗口时,程序退出
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

// 实现ActionListener接口中的actionPerformed方法,处理按钮点击事件
public void actionPerformed(ActionEvent e)
{
String str = JOptionPane.showInputDialog(null, "请输入数字字符序列", "输入对话框",
JOptionPane.INFORMATION_MESSAGE); //创建输入对话框.(依赖组件、显示消息、标题、外观)

if(str!=null)// 如果用户输入了内容(没有点击取消)
{
m = p.matcher(str);//用编译好的模式对象创建匹配器,在输入字符串中查找非数字字符
while(m.find()) // 使用while循环查找所有非数字字符的匹配项
{
// 如果找到非数字字符,显示警告对话框,提示用户输入了非法字符
JOptionPane.showMessageDialog(this, "您输入了非法字符", "消息对话框", JOptionPane.WARNING_MESSAGE);
// 再次显示输入对话框,让用户重新输入
str = JOptionPane.showInputDialog(null, "请输入数字字符序列");
// 重新创建匹配器,用于在新输入的字符串中查找非数字字符
m = p.matcher(str);
}

//显示确认对话框,询问用户是否确认输入正确
int n = JOptionPane.showConfirmDialog(this, "确认正确吗?", "确认对话框", JOptionPane.YES_NO_OPTION);
if(n == JOptionPane.YES_OPTION)
{
save.append("\n"+str);
}
}
}
}

public class demo2 {
public static void main(String args[])
{
new Dwindow();
}
}

颜色对话框

javax.swing包中的JColorChooser类的静态方法public static Color showDialog(Component com, String title, Color initialColor)创建一个颜色对话框.
其中参数com指定对话框所依赖的组件,title指定对话框的标题,initialColor指定对话框返回的初始颜色,即对话框消失后返回的默认值。
颜色对话框可根据用户在颜色对话框中选择的颜色返回一个颜色对象。

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
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;

class ColorWin extends JFrame implements ActionListener
{
JButton buttonOpen,showColor;
ColorWin(String s)
{
// ---
setTitle(s);

// ---
buttonOpen = new JButton("打开颜色对话框");
buttonOpen.addActionListener(this);
add(buttonOpen,BorderLayout.NORTH);

// ---
showColor = new JButton();
add(showColor,BorderLayout.CENTER);

// ---
setBounds(60,60,300,300);
setVisible(true);

// ---
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void actionPerformed(ActionEvent e)
{
//创建颜色对话框
Color newColor = JColorChooser.showDialog(this, "调色板", showColor.getBackground());
if(newColor!=null)
{
showColor.setBackground(newColor);
}
}
}

public class demo3 {
public static void main(String args[])
{
new ColorWin("带颜色对话框的窗口");
}
}

文件对话框

文件对话框提供从文件系统中进行文件选择的界面。
JFileChooser对象调用
showDialog(Component parentComponent, String s)
showOpenDialog(Component parentComponent)
showSaveDialog(Component parentComponent)
使一个有模式对话框显示在桌面,该对话框称作文件对话框
文件对话框将在参数指定的组件parentComponent的正前方显示
如果parentComponent为null,则在系统桌面的正前方显示。

当文件对话框消失后,上述方法返回整型常量,返回的值依赖于单击了对话框上的“确认”按钮还是“取消”按钮。
JFileChooser.APPROVE_OPTION
JFileChooser.CANCEL_OPTION

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
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;

class FileWindow extends JFrame implements ActionListener
{
JButton buttonFile;
JTextArea text;
JFileChooser fileChooser; //文件对话框
FileWindow()
{
fileChooser = new JFileChooser("c:/");

// ---
buttonFile = new JButton("打开文件");
buttonFile.addActionListener(this);
add(buttonFile, BorderLayout.NORTH);

// ---
text = new JTextArea("显示文件内容");
add(new JScrollPane(text), BorderLayout.CENTER);
// ---
setBounds(60,60,300,300);
setVisible(true);
// ---
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void actionPerformed(ActionEvent e)
{
text.setText(null);
int n = fileChooser.showOpenDialog(null);
if(n == JFileChooser.APPROVE_OPTION)
{
File file = fileChooser.getSelectedFile();
// ---
try
{
FileReader readfile = new FileReader(file);
BufferedReader in = new BufferedReader(readfile);
String s = null;
while( (s=in.readLine()) != null )
{
text.append(s+"\n");
}
}
catch(IOException ee){}
}
}
}


public class demo4 {
public static void main(String args[])
{
new FileWindow();
}
}

多文档界面

实现多文档界面(MDI)

  • 在一个JFrame窗体中添加若干个内部窗体,内部窗体由JInternalFrame类负责创建。这些内部窗体被限制在JFrame窗体中。
  • 在使用内部窗体时,需要将内部窗体事先添加到JDesktopPane桌面窗格中,一个桌面窗格可以添加若干个内部窗体,这些内部窗体将被限制在该桌面窗格中,然后把桌面窗格添加到JFrame窗体即可。
  • 桌面窗格使用方法add(JInternalFrame e, int layer)添加内部窗体,并指定内部窗体所在的层次。

布局设计

  • java.awt包中的FlowLayout、BorderLayout、CardLayout、GridLayout布局类
    JFrame窗体,默认布局是BorderLayout布局。
  • java.swing.border包中的BoxLayout布局类
  • 容器可使用方法setLayout(布局对象);来设置自己的布局。

FlowLayout布局

居中对齐
FlowLayout flow = new FlowLayout();

  • con.setLayout(flow);则con可使用Container类提供的add方法将组件顺序地添加到容器中.
  • 组件按照加入的先后顺序从左向右排列,一行排满之后就转到下一行继续从左至右排列。
  • FlowLayout布局对象调用setHgap(int hgap)方法和setVgap(int vgap)方法可设置布局的水平间隙和垂直间隙。
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
import java.awt.*;
import javax.swing.*;

class WindowFlow extends JFrame
{
JButton b[]; //按钮数组
WindowFlow(String s)
{
// ---
setTitle(s);

// ---
b = new JButton[10];

// FlowLayout布局
FlowLayout flow = new FlowLayout();
flow.setAlignment(FlowLayout.LEFT);
//设置布局的水平间隙和垂直间隙。
flow.setHgap(20);
flow.setVgap(8);
this.setLayout(flow);

// ---
for(int i=0; i<b.length; i++)
{
b[i] = new JButton("" + i);
this.add(b[i]);
}

// ---
validate();

// ---
setBounds(100, 100, 200, 160);
setVisible(true);

// ---
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}

public class demo5 {
public static void main(String args[])
{
new WindowFlow("FlowLayout布局窗口");
}
}

BorderLayout布局

是Window型容器的默认布局,例如JFrame和JDialog都是Window类的间接子类

  • 容器空间简单地划分为东、西、南、北、中五个区域。
  • 每加入一个组件都应指明把这个组件添加在哪个区域中.
  • 区域由BorderLayout中的静态常量EAST, WEST, SOUTH, NORTH, CENTER表示。
  • 添加到某个区域的组件将占据这个区域。每个区域只能放置一个组件,
  • 如果向某个已放置了组件的区域再放置一个组件,那么先前的组件将被后者替换掉。
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
import javax.swing.*;
import java.awt.*;

public class demo6 {
public static void main(String args[])
{
// ---
JFrame win = new JFrame("窗体");

// ---
JButton bSouth = new JButton("南");
JButton bNorth = new JButton("北");
JButton bEast = new JButton("东");
JButton bWest = new JButton("西");
JTextArea bCenter = new JTextArea("中心");

// ---
win.add(bNorth, BorderLayout.NORTH);
win.add(bSouth, BorderLayout.SOUTH);
win.add(bEast, BorderLayout.EAST);
win.add(bWest, BorderLayout.WEST);
win.add(bCenter, BorderLayout.CENTER);

// ---
win.validate();

// ---
win.setBounds(100,100,300,300);
win.setVisible(true);

// ---
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

CardLayout布局

可容纳多个组件,但是实际上同一时刻容器只能从这些组件中选出一个来显示,被显示的组件将占据所有的容器空间。
JTabbedPane创建的对象是一个轻容器,称作选项卡窗格。选项卡窗格的默认布局是CardLayout布局。

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
import javax.swing.*;
import java.awt.*;

class MyWin extends JFrame
{
JTabbedPane p; //声明一个JTabbedPane类型的变量p
Icon icon[]; // 声明一个Icon类型的数组icon,用于存储图标
//Icon是一个接口,位于javax.swing包中。Icon接口代表一个小型的、固定大小的图片,通常用于装饰组件,例如按钮、标签等
String imageName[] = {"a.jpg", "b.jpg", "c.jpg", "d.jpg", "D:\\Java\\code\\course\\out\\production\\course\\Page\\a.jpg"}; //字符串数组 图片名称

public MyWin() //构造函数
{
icon = new Icon[imageName.length];
for(int i=0; i<icon.length; i++)
{
icon[i] = new ImageIcon(imageName[i]);// // ImageIcon用于从指定文件路径加载图像并创建一个图标
}

p = new JTabbedPane(JTabbedPane.LEFT);//创建JTabbedPane对象p,选项卡标签的位置在左侧
for(int i=0; i<icon.length; i++)
{
int i2 = i + 1;
p.add("观看第" + i2 + "个图片", new JButton(icon[i]));//将组件com添加到容器当中
}

add(p, BorderLayout.CENTER);

p.validate();

validate();

setBounds(100, 100, 500, 300);
setVisible(true);

setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}

public class demo7 {
public static void main(String args[])
{
new MyWin();
}
}

GridLayout布局

把容器划分成若干行乘若干列的网格区域,组件就位于这些划分出来的小格中。
创建布局对象,指定划分网格的行数m和列数nGridLayout grid = new GridLayout(10,8);
调用方法add将组件加入容器,组件进入容器的顺序:从上到下、从左到右

BoxLayout布局

盒式布局
BoxLayoutjava.swing.border包中。
java swing包提供了Box类,该类也是Container类的一个子类,创建的容器称作一个盒式容器,盒式容器的默认布局是盒式布局,而且不允许更改盒式容器的布局。

  • 在策划程序的布局时,可利用容器的嵌套,在某个容器中嵌入几个盒式容器,达到布局的目的。
  • 使用盒式布局的容器将组件排列在一行或一列,这取决于创建盒式布局对象时,指定了行排列还是列排列
  • 在行型盒式布局容器中添加的组件的上沿在同一水平线上。在列型盒式布局容器中添加的组件的左沿在同一垂直线上。
  • 使用Box类的静态方法createHorizontalBox() -> 行型盒式布局的盒式容器
  • 使用Box类的静态方法createVerticalBox() -> 列型盒式布局的盒式容器
  • 控制盒式布局容器中组件之间的距离,需用水平支撑或垂直支撑。
  • Box类调用静态方法createHorizontalStrut(int width)可得一个不可见的水平Strut类型对象,称做水平支撑,水平宽度是width
  • Box类调用静态方法createVerticalStrut(int height)可得一个不可见的垂直Strut类型对象,称做垂直支撑。参数height决定垂直支撑的高度 。
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
import javax.swing.*;
import java.awt.*;

class WindowBox extends JFrame
{
Box baseBox, boxV1, boxV2;
WindowBox()
{
boxV1 = Box.createVerticalBox(); //列型盒式布局的盒式容器
boxV1.add(new JLabel("输入您的姓名"));
boxV1.add(Box.createVerticalStrut(8)); //垂直支撑的高度
boxV1.add(new JLabel("输入email"));
boxV1.add(Box.createVerticalStrut(8)); //垂直支撑的高度
boxV1.add(new JLabel("输入您的职业"));

boxV2 = Box.createVerticalBox(); //列型盒式布局的盒式容器
boxV2.add(new JTextField(16)); //JTextField文本输入框
boxV2.add(Box.createVerticalStrut(8)); //垂直支撑的高度
boxV2.add(new JTextField(16));
boxV2.add(Box.createVerticalStrut(8)); //垂直支撑的高度
boxV2.add(new JTextField(16));

baseBox = Box.createHorizontalBox(); //行型盒式布局的盒式容器
baseBox.add(boxV1);
baseBox.add(Box.createHorizontalStrut(10)); //水平宽度
baseBox.add(boxV2);

// FlowLayout布局
FlowLayout flow = new FlowLayout();
flow.setAlignment(FlowLayout.LEFT);
setLayout(flow);

this.add(baseBox);
validate();
setBounds(120,125,200,200);
setVisible(true);

setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}

public class demo8 {
public static void main(String args[])
{
new WindowBox();
}
}

null布局

空布局容器

  • p是某个容器,p.setLayout(null);把p的布局设置为空布局。
  • 空布局容器可以准确地定位组件在容器中的位置和大小。
  • setBounds(int a, int b, int width, int height)方法是所有组件都拥有的一个方法,组件调用该方法可以设置组件本身的大小和在容器中的位置。
  • 向空布局的容器p添加一个组件com
    • add(com)方法向容器添加组件
    • 组件com再调用setBounds(int a, int b, int width, int height)方法设置该组件在容器中的位置和本身的大小
    • 组件都是一个矩形结构
    • 方法中的参数a,b是被添加的组件com的左上角在容器中的位置坐标,即该组件距容器左面a个像素,距容器上方b个像素;width和height是组件com的宽和高。

菜单组件

窗口 -> 菜单条(menu bar)-> 菜单(menu)-> 菜单项(menu item)

JMenuBar菜单条

  • JComponent类的子类JMenuBar的一个实例就是一个菜单条
  • 将菜单条放置到窗口中的方法public void setJMenuBar(JMenuBar menubar);
  • 只能向窗口添加一个菜单条。

JMenu菜单

  • JComponent类的子类JMenu类负责创建菜单
  • JMenu(String s)建立一个指定标题的菜单,标题由参数s确定。
  • public void add(MenuItem item)向菜单增加由参数item指定的菜单项对象。
  • public void add(String s)向菜单增加指定的选项。
  • public JMenuItem getItem(int n)得到指定索引处的菜单项。
  • public int getItemCount()得到菜单项数目。

JMenuItem菜单项

  • JMenuItem是JMenu的父类,该类是负责创建菜单项的,即JMenuItem的一个实例就是一个菜单项
  • 菜单项将被放在菜单里
  • JMenuItem(String s)构造有标题的菜单项。
  • JMenuItem(String s, Icon icon)构造有标题和图标的菜单项。
  • public void setEnabled(boolean b)设置当前菜单项是否可被选择。
  • public String getLabel()得到菜单项的名字。
  • public void setAccelerator(KeyStroke keyStroke)为菜单项设置快捷键。
  • 向方法的参数传递一个KeyStroke对象,可以使用KeyStroke类的类方法:public static KeyStroke getKeyStroke(char keyChar)返回一个KeyStroke对象。 也可使用KeyStroke类的静态方法public static KeyStroke getKeyStroke(int keyCode, int modifiers)返回一个KeyStroke对象。
    • 参数keyCode取值范围:KeyEvent.VK_A~KeyEvent.VK_Z
    • 参数modifiers取值范围:InputEvent.ALT_MASK, InputEvent.CTRL_MASK和InputEvent.SHIFT_MASK

嵌入子菜单

嵌入子菜单JMenu是JMenuItem的子类,因此菜单项本身也可以是一个菜单,称这样的菜单项为子菜单
设置图标Icon icon = new ImageIcon(“open.gif”);

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
import javax.swing.*;
import java.awt.event.InputEvent;// 导入处理输入事件的包
import java.awt.event.KeyEvent; // 导入处理键盘事件的包

class FirstWindow extends JFrame
{
JMenuBar menubar; //JMenuBar菜单条
JMenu menu; //JMenu菜单
JMenuItem item1,item2; //JMenuItem菜单项

FirstWindow(String s)// 构造方法,用于初始化窗口
{
setTitle(s);

item1 = new JMenuItem("打开", new ImageIcon("open.gif"));
item2 = new JMenuItem("保存", new ImageIcon("save.gif"));
//为菜单项设置快捷键
//getKeyStroke(char keyChar)返回一个KeyStroke对象
// 为菜单项“打开”设置快捷键Ctrl+O
item1.setAccelerator(KeyStroke.getKeyStroke("ctrl O"));
//getKeyStroke(int keyCode, int modifiers)返回一个KeyStroke对象
// 为菜单项“保存”设置快捷键Ctrl+S
item2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));

menu = new JMenu("文件"); //菜单
menu.add(item1);
menu.addSeparator();
menu.add(item2);

menubar = new JMenuBar(); //菜单条
menubar.add(menu); //菜单条中加入菜单
setJMenuBar(menubar); //将菜单条放置到窗口中

validate();

setSize(160,170);
setLocation(120,120);
setVisible(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}

public class demo9 {
public static void main(String args[]) {
FirstWindow win = new FirstWindow("一个简单的窗口");
}
}

文本组件

JTextField文本框

1
2
3
4
5
6
JTextField(int x)//创建文本框对象,可见字符个数由参数x指定。 
JTextField(String s)//创建文本框对象,初始字符串为s。
public void setText(String s)//文本框对象调用该方法可以设置文本框中的文本为参数s指定的文本。
public String getText()//文本框对象调用该方法可以获取文本框中的文本。
public void setEditable(boolean b)//文本框对象调用该方法可以指定文本框的可编辑性。
public void setHorizontalAlignment(int alignment)//设文本在文本框中的对齐方式,其中alignment的有效值确定对齐方式。

JPasswordField密码框

setEchoChar(char c)设置回显字符(默认的回显字符是‘*’)
char[] getPassword()方法返回密码框中的密码。

ActionEvent事件

处理组件上发生的界面事件
当用户在有输入焦点的文本框(JTextField)中按回车键、单击按钮、在一个下拉式列表中选择一个条目等操作时,都会发生界面事件。程序有时需要对发生的事件作出反应,来实现特定的任务。
事件源监视/监听器处理事件的接口

事件源

eg:如文本框、按钮、下拉式列表等。

监视/监听器

eg:对于文本框,这个方法是addActionListener(ActionListener listener),对于获取了监视器的文本框对象,在文本框(JTextField)获得输入焦点之后,如果用户按回车键,Java运行系统就自动用ActionEvent类创建一个对象,即发生了ActionEvent事件。

处理事件的接口

注意到发生ActionEvent事件的事件源对象获得监视器的方法是:
addActionListener(ActioListenerlistener);

  • 该方法中的参数是ActionListener类型的接口,须将一个实现ActionListener接口的类创建的对象作为传递给该方法的参数,使得该对象成为事件源的监视/监听器。
  • 监视/监听器负责调用特定的方法来处理事件,也就是说创建监视/监听器的类必须提供处理事件的特定方法,即实现接口中的方法。
  • Java采用接口回调技术来处理事件,当事件源发生事件时,接口立刻通知监视/监听器自动调用实现的某个接口方法,该接口方法规定了怎样处理事件的操作。接口回调这一过程对程序是不可见的,Java在设计组件事件时已经设置好了这一回调过程,程序只需让事件源获得正确的监视/监听器,即将实现了正确接口的对象的引用传递给方法。

ActionEvent类中的方法

  • ActionEvent事件对象调用方法public Object getSource()可以返回发生ActionEvent事件的对象的引用。
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
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class MyWindow extends JFrame
{
JTextField text;
PoliceStation police;//text的事件监视器由PoliceStation类负责创建

MyWindow()
{
setLayout(new FlowLayout());

police = new PoliceStation();

text = new JTextField(10);
add(text);
text.addActionListener(police);
//text是事件源,police是监视器

setBounds(100,100,150,150);
setVisible(true);
validate();
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}

class PoliceStation implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String str = e.getActionCommand();
System.out.println(str);
System.out.println(str.length());
}
}

public class demo0 {
public static void main(String args[])
{
MyWindow win = new MyWindow();
}
}
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
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class PoliceWindow extends JFrame implements ActionListener
{
// titleText和passwordText有监视器
JTextField titleText;
JPasswordField passwordText;

PoliceWindow()
{
titleText = new JTextField(10);
add(titleText);
titleText.addActionListener(this); //监视器

passwordText = new JPasswordField(10);
passwordText.setEchoChar('*'); //设置回显字符
add(passwordText);
passwordText.addActionListener(this); //监视器

validate();
setLayout(new FlowLayout());
setBounds(100, 100, 150, 150);
setVisible(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}

public void actionPerformed(ActionEvent e)
{
JTextField textSource = (JTextField)e.getSource();
if(textSource==titleText)
{
this.setTitle(titleText.getText()); //将窗体的标题更改为当前titleText中的文本
}
else
{
if(textSource == passwordText)
{
//passwordText中输入密码回车后,监视器负责将密码显示在titleText中
char[] c = passwordText.getPassword();
titleText.setText(new String(c));
}
}
}
}

public class demo11 {
public static void main(String args[])
{
PoliceWindow policeWin = new PoliceWindow();
}
}
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
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.math.*;

class MathWindow extends JFrame
{
JTextField inputText,showText;
MathWindow()
{
inputText = new JTextField(10);
add(inputText);
showText = new JTextField(10);
add(showText);
inputText.addActionListener(new ActionListener() //使用匿名对象作为inputText的监视器
{
public void actionPerformed(ActionEvent e)
{
String s = inputText.getText();
//当在inputText中输入一个数字字符串后,监视器负责计算这个数的平方
try
{
BigInteger n = new BigInteger(s);
n = n.pow(2);
showText.setText(n.toString());//将结果放入showText中
}
catch(NumberFormatException e2)
{
showText.setText("请输入数字字符");
inputText.setText(null);
}
}
});
setLayout(new FlowLayout());
validate();
setBounds(100,100,260,190);
setVisible(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}

public class demo12 {
public static void main(String args[])
{
MathWindow win=new MathWindow();
}
}

菜单项上的ActionEvent事件

单击某个菜单项可以发生ActionEvent事件。菜单项使用addActionListener(ActionListener listener)方法获得监视器。

JTextArea文本区

构造

1
2
3
4
5
6
7
8
JTextArea(int rows, int columns)    //构造一个可见行和可见列分别是rows、columns的文本区。
setLineWrap(boolean b) //方法决定输入的文本能否在文本区的右边界自动换行;
setWrapStyleWord(boolean b) //决定是以单词为界(b取true时)或以字符为界(b 取false时)进行换行。
append(String s)//尾加文本。
insert(String s, int x)//在文本区的指定位置处插入文本。
getCaretPosition()//获取文本区中输入光标的位置。
copy() / cut() //将文本区中选中的内容拷贝或剪切到系统的剪贴板。
paste()//将系统剪贴板上的文本数据粘贴在文本区中。
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
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

class EditWindow extends JFrame implements ActionListener
{
JMenuBar menubar; //菜单条
JMenu menu; //菜单
JSplitPane splitPane; //拆分窗格
JMenuItem itemCopy,itemCut,itemPaste;//菜单项
JTextArea text1,text2; //文本区

EditWindow(String s)
{
setTitle(s);
setSize(260, 270);
setLocation(120, 120);
setVisible(true);

itemCopy = new JMenuItem("复制");
itemCut = new JMenuItem("剪切");
itemPaste = new JMenuItem("粘贴");

itemCopy.addActionListener(this);
itemCut.addActionListener(this);
itemPaste.addActionListener(this);
menu = new JMenu("编辑");
menu.add(itemCopy);
menu.add(itemCut);
menu.add(itemPaste);

menubar = new JMenuBar();
menubar.add(menu);
setJMenuBar(menubar);

text1 = new JTextArea();
text2 = new JTextArea();
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, text1, text2);//行型布局
splitPane.setDividerLocation(120);
add(splitPane, BorderLayout.CENTER);

validate();

setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}

public void actionPerformed(ActionEvent e)
{
if(e.getSource() == itemCopy)
{
text1.copy();//将文本区中选中的内容拷贝到系统的剪贴板。
}
else
{
if(e.getSource() == itemCut)
{
text1.cut();//将文本区中选中的内容剪切到系统的剪贴板。
}
else
{
if(e.getSource()==itemPaste)
{
text2.paste();//将系统剪贴板上的文本数据粘贴在文本区中。
}
}
}
}
}

public class demo13 {
public static void main(String args[])
{
EditWindow win = new EditWindow("窗口");
}
}

文本区上的DocumentEvent事件

文本区可以触发DocumentEvent事件,DocumentEvent类在javax.swing.event包中。
用户在文本区组件的UI代表的视图中进行文本编辑操作,使得文本区中的文本内容发生变化,将导致该组件所维护的文档模型中的数据发生变化,从而导致DocumentEvent事件的发生。
需要使用addDocumentListener() -> 向组件维护的文档注册监视器
监视器需实现DocumentListener接口
该接口中有三个方法:

  • public void changedUpdate(DocumentEvent e)
  • public void removeUpdate(DocumentEvent e)
  • public void insertUpdate(DocumentEvent e)
    文本区调用 getDocument()方法返回维护的文档。
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
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.regex.*;
import javax.swing.event.*;

class PatternWindow extends JFrame implements DocumentListener, ActionListener//向组件维护的文档注册监视器、监视器
{
JTextArea inputText,showText;
JTextField patternText;
Pattern p; //模式对象
Matcher m; //匹配对象
PatternWindow()
{
inputText = new JTextArea();
showText = new JTextArea();
patternText = new JTextField("[^\\s\\d\\p{Punct}]+");
patternText.addActionListener(this); //监视器
add(patternText, BorderLayout.NORTH); //BorderLayout布局:北 模式串
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1, 2)); //网格布局
panel.add(new JScrollPane(inputText));
panel.add(new JScrollPane(showText));
add(panel, BorderLayout.CENTER); //BorderLayout布局:中 输入&输出区域

validate();
(inputText.getDocument()).addDocumentListener(this); // 向文档注册监视器
setBounds(120, 120, 260, 270);
setVisible(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}

public void changedUpdate(DocumentEvent e)
{
hangdleText();
}
public void removeUpdate(DocumentEvent e)
{
changedUpdate(e);
}
public void insertUpdate(DocumentEvent e)
{
changedUpdate(e);
}

public void hangdleText()
{
showText.setText(null);
String s = inputText.getText(); //用户在文本区inputText进行编辑操作
p = Pattern.compile(patternText.getText()); //初始化模式对象
m = p.matcher(s);
//文本区showText将显示第一个文本区中所有和指定模式匹配的字符串
while(m.find())
{
showText.append("从"+m.start()+"到"+m.end()+":");
showText.append(m.group()+":\n");
}
}

public void actionPerformed(ActionEvent e)
{
hangdleText();
}
}

public class demo14 {
public static void main(String args[])
{
new PatternWindow();
}
}

组件常用方法

组件的颜色

1
2
3
4
5
6
7
public void setBackground(Color c)//设置组件的背景色。 
public void setForeground(Color c)//设置组件的前景色。
public Color getBackground(Color c)//获取组件的背景色。
public Color getForeground(Color c)//获取组件的前景色。
//Color类是java.awt包中的类,该类创建的对象称为颜色对象。
//用Color类的构造方法可以创建一个颜色对象,其中red、green和blue的取值在0~255之间
public Color(int red, int green, int blue)

组件透明

1
2
3
4
public void setOpaque(boolean isOpaque)
//isOpaque取false时组件被设置为透明,取值true时组件被设置为不透明。
public boolean isOpaque()
//当组件不透明时该方法返回true,否则返回false

组件的边框

1
2
3
4
// 组件默认的边框是一个黑边的矩形。
public void setBorder(Border border)//设置组件的边框。
//该方法的参数是一个接口,须向该参数传递一个实现接口Border类的实例,如果传递一个null,组件将取消边框。
public Border getBorder()//返回边框。

组件的字体

1
2
3
4
5
6
7
public void setFont(Font f)//组件调用该方法设置组件上的字体。例如,文本组件调用该方法可以设置文本组件中的字体。
public Font getFont(Font f)//组件调用该方法获取组件上的字体。
//java.awt包中的Font类,该类创建的对象称为字体对象
//Font类的构造方法 ->创建字体对象
public Font(String name, int style, int size);
//name字体的名字,若系统不支持字体的名字,将取默认的名字创建字体对象。
//style决定字体的样式,取值是一个整数
1
2
3
4
5





按钮与标签组件

复选框与单选按钮组件

列表组件

表格组件

树组件

进度条组件

窗口事件

鼠标事件

焦点事件

键盘事件

AWT线程

计时器

MVC设计模式

播放音频

按钮绑定到键盘

发布应用程序