第 5章 图形用户界面
5.1 文本框和文本区
5.2 标 签
5.3 按 钮
5.4 选 择 框
5.5 画 布
5.6 面板与布局设计
5.7 窗 口
5.8 菜 单
5.9 对 话 框
5.1 文本框和文本区
5.1.1 文本框及处理事件
1,文本框的创建
2.文本框处理事件例 5-2:两个空白文本框,当在第一个文本框内输入字符时,在文本框内显示,*”
号,输入完毕按回车键后,在第二个文本框内显示,The end。
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Ex6_2 extends Applet{
TextField tf1=new TextField(20);
TextField tf2=new TextField(20);
public void init(){
add(tf1);
tf1.setEchoChar('*');
add(tf2);
tf1Listener al = new tf1Listener();
tf1.addActionListener(a1);
}
class tf1Listener implements
ActionListener{
public void actionPerformed(ActionEvent
e) {
tf2.setText("The end");
}
}
}
运行结果见图 5-2。
图 5-1
5.1.2 文本区及处理事件例 5-4:在 Applet中添加一个文本框和一个文本区,每当在文本框中输入一个字符时,在文本区内就附加一行文本,The
text is changed。
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Ex6_4 extends Applet{
TextField tf1=new TextField(20);
TextArea ta1=new TextArea (null,6,40);
public void init(){
add(tf1);
add(ta1);
tf1.addTextListener(new TextL());
}
class TextL implements TextListener{
public void textValueChanged(TextEvent e)
{
ta1.append("\nThe text is changed");
}
}
}
运行结果见图 5-4。
图 5-4
5.2 标 签标签( Label) 是 AWT构件中最简单的一种构件,所谓标签实质上就是一段文字,但它与文字不同的是它是一个对象,
所以在每次 repaint时,不用重新添加。标签在 GUI界面中通常作为提示信息使用。
标签构件的构造方法如下 。
( 1) Label() 构造一个空的标签 。
( 2) Label( String str) 构造一个以
String str为内容的标签 。
( 3) Label( String str,int align) 定义一个以 String str为内容的标签 。
5.3 按 钮
5.3.1 按钮按钮 ( Button) 是 GUI用户界面中常用的元素,它是用户输入命令的一个重要工具 。 当用鼠标单击某个按钮该按钮获得焦点时,在键盘上按回车键都会导致一个命令的执行 。 Button类有两种构造方法 。
( 1) Button() 构造一个没有标签的按钮 。
( 2) Button( String str) 构造一个以
String str为标签的按钮 。
5.3.2 按钮处理事件与按钮有关的事件有两类。
1,ActionEvent
当用鼠标单击按钮,或当按钮获得焦点时在键盘上按回车键都导致该事件的发生,此时任何实现了被注册为监听者的
ActionListener 接口的类,它的
actionPerformed()方法将被调用 。
下面的程序范例在 Applet上添加两个命令按钮,其标签分别为“显示”和“清除”,当单击“显示”按钮时,在文本区中显示:“你按下了显示按钮”,当按
“清除”按钮时则清除文本区中显示的字符。
例 5-6:文本区事件处理。
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Ex6_6 extends Applet{
Button b1=new Button("显示 ");
Button b2=new Button("清除 ");
TextArea ta1=new TextArea (null,6,40);
public void init(){
add(b1);
add(b2);
add(ta1);
b1.addActionListener(new ButtenL());
b2.addActionListener(new ButtenL());
}
class ButtenL implements ActionListener{
public void
actionPerformed(ActionEvent e) {
if (e.getSource()==b1)
ta1.append ("\n你按下了 "显示 "
按钮 ");
else
ta1.append ("\n你按下了 "清除 "
按钮 ");
}
}
}
运行结果见图 5-6。
图 5-6
2,FocusEvent
FocusEvent称作焦点事件,它的发生是指键盘光标移动到构件上并且可以接受键盘的输入。如果光标移动到一个按钮上,
称作该按钮获得焦点,反之称作失去焦点。
当一个按钮获得焦点时单击回车键即相当于用鼠标单击该按钮。如果一个文本框获得焦点就可以在该文本框中输入字符。
例 5-7:按钮和文本框检测焦点事件的例子。程序如下:
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Ex6_7 extends Applet{
TextField txt1 = new TextField("txt1",50);
TextField txt2 = new
TextField("txt2",50);
Button button1=new Button("button1");
Button button2=new Button("button2");
class Keytry implements FocusListener{
public void focusGained(FocusEvent e) {
txt1.setText("txt1:paramString()="+e.para
mString());
if (e.getSource()==txt1)
txt2.setText("txt2:focus is on txt1
");
else
txt2.setText("txt2:focus is on
button1");
}
public void focusLost(FocusEvent e) {
txt1.setText("txt1:paramString()="+e.para
mString());
txt2.setText("txt2:focus lost outside
button1 or txt1");
}
}
Keytry al = new Keytry();
public void init(){
setLayout(new FlowLayout());
txt1.addFocusListener(al);
button1.addFocusListener(al);
add(button1);
add(button2);
add(txt1);
add(txt2);
}
}
运行结果见图 5-7。
图 5-7
在上面的例子中,只有 button1和 txt1
注册了焦点事件的事件监听者,它们共享同一个事件处理程序 。 如果焦点在 button1
或 txt1上面,文本框 txt2显示焦点在哪个构件上 ( focusGaned),反之则指出无焦点
( focusLost) 。 文本框 txt1内显示事件的参数字符串,它也能指出是否有焦点 。 另外,程 序 中 的 setLayout( new
FlowLayout()) 语句是控制构件的布局用的,关于这个问题将在后面的章节中进行讨论 。
5.4 选 择 框
5.4.1 选择框
1,下拉列表框 ( Choice)
2,列表框 ( List)
3,复选框 ( Checkbox)
4,单选框
( Checkbox group-Radio Button)
5.4.2 选择框处理事件例 5-12:选择框检测 ItemEvent事件的例子。
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Ex6_12 extends Applet
implements ItemListener{
TextArea ta1=new TextArea (null,6,40);
String subject[]={"语文 ","数学 ","政治
","外语 ","物理 ","化学 "};
Checkbox cb[]=new Checkbox[6];
public void init(){
add(new Label("请选择,"));
for(int I=0;I<6;I++){
cb[I]= new Checkbox(subject[I]);
add(cb[I]);
cb[I].addItemListener(this);
}
add(ta1);
}
public void itemStateChanged(ItemEvent e)
{
ta1.append("\n你在复选框中的选择是:
"+e.getItem());
}
}
运行结果见图 5-12。
图 5-12
5.5 画 布例 5-13:创建一个画布 。
import java.awt.*;
import java.applet.Applet;
import java.util.*;
public class mycanvas extends Applet {
public void init() {
MyCanvas1 mc = new MyCanvas1();
mc.setBackground(Color.green);
mc.setSize(150,150);
add(mc);
}
}
class MyCanvas1 extends Canvas{
public void paint(Graphics g){
g.fillOval(40,20,80,80);
}
}
运行结果见图 5-13。
图 5-13
5.6 面板与布局设计
5.6.1 布局管理器
1,FlowLayout类
2,BorderLayout类例 5-15:边界布局使用实例。
import java.awt.*;
import java.applet.Applet;
public class Ex6_15 extends Applet {
public void init(){
setLayout(new BorderLayout(0,0));
add(new
Button("North"),BorderLayout.NORTH);
add(new
Button("South"),BorderLayout.SOUTH);
add(new
Button("East"),BorderLayout.EAST);
add(new
Button("West"),BorderLayout.WEST);
add(new
Button("Center"),BorderLayout.CENTER
);
}
}
运行结果见图 5-15。
图 5-15
3,GridLayout类
4,布局设计中的绝对定位
5.6.2 面板面板 ( Panel) 是一个容器类,它可以包含其他的构件或另外的面板,并且可以使用布局管理器对其内部的构件进行管理 。 其实 Aapplet本身就是面板的一个子类,
它就是一个特殊的面板 。 面板缺省的布局方式是 FlowLayout。
面板的构造方法如下。
( 1) Panel() 用缺省布局方式
( FlowLayout) 创建一个面板。
( 2) Panel( LayoutManager layout)
用指定布局方式创建一个面板。
面板的常用方法如下。
( 1) public void add( Component
comp) 为容器添加一个构件。
( 2) public void remove( Component
comp) 为容器去除一个构件。
( 3) public void setSize( int width,
int height) 为容器设定宽和高。
( 4) public void setFont( Font f) 为容器设定字体。
( 5) public void setLocation( int x,
int y) 设定定坐标位置。
( 6) public void paint( Graphics g)
画出容器。
( 7) public void update( Graphics g)
先清除容器的内容再调用 paint方法重画容器。
( 8) public void repaint() 调用容器的 updata方法。
使用面板可以使构件的排列具有更大的灵活性。可以将不同的构件分组,然后将同一组的构件放在一个面板上。下面是使用面板安排构件的一个例子。
例 5-18:面板的使用
import java.awt.*;
import java.applet.Applet;
public class Ex6_18 extends Applet {
public void init() {
setLayout(new
FlowLayout(FlowLayout.LEFT));
Panel p1 = new Panel();
add(p1);
p1.add(new Label("Your name,"));
p1.add(new TextField(30));
Panel p2 = new Panel();
add(p2);
p2.add(new Label("Sex,"));
CheckboxGroup cbg = new
CheckboxGroup();
p2.add(new Checkbox("Male ",cbg,
true));
p2.add(new Checkbox("Female ",cbg,
false));
Panel p3 = new Panel();
add(p3);
p3.add(new Label("What are you like,
"));
p3.add(new Checkbox("Apple "));
p3.add(new Checkbox("orange "));
p3.add(new Checkbox("Strawberry
"));
p3.add(new Checkbox("Peach "));
Panel p4 = new Panel();
add(p4);
p4.add(new Label("How much do you
eat them per week,"));
Choice c = new Choice();
c.addItem("less than 1kg ");
c.addItem("1kg to 3kg");
c.addItem("more than 3kg");
p4.add(c);
Panel p5 = new Panel();
add(p5);
p5-add(new Label("What's your
opnion of eating fruit,"));
add(new TextArea("I think ",3,60));
Panel p6 = new Panel();
add(p6);
p5-add(new Button(" OK "));
p5-add(new Button("Clear "));
}
}
运行结果见图 5-18。
图 5-18
在这个程序中,加入了若干个 Panel
类,在屏幕上显示在同一行中的构件都属于同一个 Panel。 布局管理器的缺省设置是
FlowLayout,排列方式缺省为居中 。 现在版面仍是 FlowLayout,排列方式改成靠左 。
在各个 Panel中,使用相同的版面 。 当然也可将各个 Panel设置成不同的版面,这样效果会不同 。
5.7 窗 口窗口是一个最重要的容器类构件,在独立的 Java应用程序中,所有的用户界面构件都是添加在窗口当中的 。 在 Java的
AWT工具包中有一个窗口 ( Window) 类,
但它生成的窗口没有标题栏和改变窗口大小的按钮,在实际的应用中经常使用的是它的两个子类 Frame( 框架 ) 和 Dialog( 对话框 ) 。 框架 ( Frame) 是带标题和按钮的顶层窗口 。 从类的层次上来看,它和
Panel都属于 Container类 。
5.8 菜 单
5.8.1 菜单( Menu)
在 GUI界面中,菜单一般位于窗口上方标题栏下面的位置,它是一个图形用户界面不可缺少的组成部分。在 Java中这一部分是由以下几个类实现的。
1,MenuBar
MenuBar又称菜单条,一个菜单条构件是一个水平菜单,它只能加入到一个框架中,并成为所有菜单树的根。 MenuBar的构造方法是
MenuBar(),在构造之后,还要用 setMenuBar()
方法将它设置成窗口的菜单条,然后按照从左到右的顺序添加它所包含的下拉菜单。
菜单条不支持监听者。作为普通菜单行为的一部分,在菜单条的区域中发生的预期事件会被自动处理。
2,Menu
Menu又称菜单或下拉菜单,它可以加入到一个菜单条或者另一个菜单中。 Menu
类的构造方法有两种。
Menu( String str) 用给定的标识构造一个菜单。
Menu( String str,boolean b) 用给定的标识构造一个菜单。如果布尔值为
false,那么当释放鼠标按钮后,菜单项会消失。如果布尔值为 true,那么释放鼠标按钮后,菜单项仍将显示。
在创建 Menu对象后,使用 MenuBar
类的 add方法将其添加到菜单条中。
Disable方法可以使菜单成为不可选的,而
enable方法使它成为可选的。
在菜单中可以添加不同的内容,可以是菜单项( MenuItem),可以是菜单选项
( CheckboxMenuItem),可以是一个子菜单,也可以是分隔符。
可以将一个 ActionListener加入到菜单对象,但这种做法不常用到。通常情况下,
菜单只用来显示和控制菜单条,而这一功能是由构件本身自动提供的。
3,MenuItem和
CheckboxMenuItem
MenuItem 称为菜单项,而
CheckboxMenuItem称为菜单选项 。 它们是一个下拉菜单的具体内容,是菜单树的文本,叶,结点 。 一个菜单项一般代表一条命令,而一个菜单选项有选中和不选中两种状态 。
MenuItem类和 CheckboxMenuItem类的构造方法如下 。
MenuItem( String str),构造一个指定标识的菜单项。特别地,当一个菜单项的指定标识为,-”时,它代表一个分隔行。
CheckboxMenuItem( String str):
构造一个指定标识的菜单选项。
通常将一个 ActionListener加入到一个菜单项对象中,以提供菜单的行为。
可以用 ItemListener接口来监视菜单选项。当该菜单选项状态发生改变时,就会调用 itemStateChanged()方法。
下面是一个菜单设计的综合范例。
例 5-21:菜单设计。
import java.awt.*;
import java.awt.event.*;
public class MenuBar1 extends
WindowAdapter implement
ActionListener,ItemListener{
Frame win1 = new
Frame("MenuBar1");
MenuBar myMenu=new MenuBar();
Menu fileMenu=new Menu("File");
Menu editMenu=new Menu("Edit");
Menu helpMenu=new Menu("Help");
enu opt = new Menu("Option");
Menu change = new Menu ("Change
Color");
MenuItem filenew=new
MenuItem("New");
MenuItem fileopen=new
MenuItem("Open");
MenuItem filesave=new
MenuItem("Save");
MenuItem fileexit=new
MenuItem("Quit");
MenuItem optblue=new
MenuItem("Blue");
MenuItem optgreen=new
MenuItem("Green");
MenuItem optred=new
MenuItem("Red");
CheckboxMenuItem filemark=new
CheckboxMenuItem("Mark",true);
Label label=new Label();
MenuBar1(){
win1.setLayout(new FlowLayout());
win1.addWindowListener(this);
myMenu.add(fileMenu);
myMenu.add(editMenu);
myMenu.add(opt);
myMenu.add(helpMenu);
fileMenu.add(filenew);
fileMenu.add(fileopen);
fileMenu.add(filesave);
fileMenu.addSeparator();
fileMenu.add(fileexit);
fileexit.addActionListener(this);
fileMenu.add(filemark);
filemark.addItemListener(this);
opt.add(change);
opt.add(new MenuItem("Change
Title"));
change.add(optblue);
optblue.addActionListener(this);
change.add(optgreen);
optgreen.addActionListener(this);
change.add(optred);
optred.addActionListener(this);
win1.add(label);
win1.setMenuBar(myMenu);
win1.setSize(400,200);
win1.setVisible(true);
}
public static void main(String[] args) {
new MenuBar1();
}
public void windowClosing(WindowEvent
e) {
System.exit(0);
}
public void
actionPerformed(ActionEvent e){
if(e.getSource()==fileexit)
System.exit(0);
else if(e.getSource()==optblue)
win1.setBackground(Color.blue);
else if(e.getSource()==optgreen)
win1.setBackground(Color.green);
else if(e.getSource()==optred)
win1.setBackground(Color.red);
}
public void itemStateChanged(ItemEvent
e){
if(e.getSource()==filemark)
if(filemark.getState())
label.setText("State of mark is on!
");
else
label.setText("State of mark is off!
");
}
}
运行结果见图 5-20。
图 5-20
5.8.2 弹出式菜单
( PopupMenu)
例 5-22:弹出菜单设计。
import java.awt.*;
import java.awt.event.*;
public class pmenu extends
WindowAdapter implements
ActionListener,MouseListener{
Frame win1 = new Frame("弹出式菜单应用 ");
TextArea ta1=new TextArea();
PopupMenu mymenu=new
PopupMenu();
MenuItem filenew=new MenuItem("新建 ");
MenuItem fileopen=new MenuItem("打开
");
MenuItem filesave=new MenuItem("保存 ");
MenuItem fileexit=new MenuItem("退出
");
pmenu (){
win1.setLayout(new FlowLayout());
win1.addWindowListener(this);
mymenu.add(filenew);
mymenu.add(fileopen);
mymenu.add(filesave);
mymenu.addSeparator();
mymenu.add(fileexit);
ta1.add(mymenu);
win1.add(ta1);
ta1.addMouseListener(this);
filenew.addActionListener(this);
fileopen.addActionListener(this);
filesave.addActionListener(this);
fileexit.addActionListener(this);
win1.setSize(400,200);
win1.setVisible(true);
}
public static void main(String[] args) {
new pmenu();
}
public void
windowClosing(WindowEvent e) {
System.exit(0);
}
public void actionPerformed(ActionEvent
e){
ta1.append("你点击了
"+e.getActionCommand()+"命令。 \n");
}
public void mouseReleased (MouseEvent
e){
if(e.isPopupTrigger()) //判断是否按下鼠标右键
mymenu.show(win1,e.getX(),e.getY());//在鼠标位置显示弹出菜单
}
public void mouseClicked (MouseEvent
e){}
public void mouseEntered(MouseEvent
e){}
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent
e){}
}
运行结果见图 5-21。
图 5-21
5.9 对 话 框在 GUI图形用户界面中,对话框是一个十分重要的构件,主要用于显示提示信息和接收用户输入,程序与用户的交互主要是通过对话框来实现的 。 从外观上看,
对话框与窗口十分类似,但它一般是一个临时的窗口,所以,在对话框中一般不需要菜单条,也不需要改变窗口大小 。
对话框是由 Dialog类实现的,从类的继承关系上看,它与 Frame类都是 Window
类的子类,而 Window类是 Container类的子类,Container类又是 Component类的子类,因此对话框可以继承上述父类的所有方法。特别地,作为容器类的一个子类,
我们可以向对话框中添加任意的构件。
对话框与框架的区别在于它必须有一个父窗口,当父窗口关闭时,它其中的对话框也被关闭。另外,对话框可以是无模式和模式的。对于无模式对话框,用户可以同时与框架和对话框交互,而模式对话框在被关闭前将阻塞包括框架在内的其他所有应用程序的输入。
由于对话框是窗口的子类,所以它的缺省布局管理器是 Border Layout。
5.9.1 自定义对话框
Dialog类的构造方法有两种 。
( 1) Dialog( Frame win,boolean b)
构造一个非可视的对话框,用户可通过
show方法将其变为可视的 。
( 2) Dialog( Frame win,String str,
boolean b),构造一个非可视的对话框 。
5.9.2 文件对话框文件对话框 ( FileDialog) 是对文件进行存取时出现的对话框,它是由
FileDialog类实现的,它的构造方法有两种 。
( 1 ) FileDialog( Frame parent,
String titel) 构造一个读文件对话框 。
Frame类型参数代表文件对话框的拥有者,
String类型参数作为文件对话框的标题 。
( 2) FileDialog( Frame parent,
String titel,int mode) 构造一个文件对话框。 int类型参数确定是读文件对话框还是写文件对话框,它的值可以是
FileDialog.LOAD或 FileDialog.SAVE。 其余参数含义与上相同。同样在构造完一个文件对话框之后,它仍是非可视的,需要使用
show方法使其变为可视的。例如:
FileDialog fd = new FileDialog(window,
"Open File",FileDialog.SAVE);
fd.show();
为创建一个写文件对话框。其父窗口是 window,标题是 Open File 。
通常并不需要处理 FileDialog的事件,
但需要调用一些常用的函数进行文件操作。
常用的文件操作函数如下:
public String getDirectory() 返回文件对话框中的路径。
public void setDirectory( String dir)
设置路径。
public string getFile() 返回文件名。
public void setFile( String file) 设置默认文件名。
public FilenameFilter( FilenameFilter
filter) 返回当前文件过滤器。
public void setFilenameFilter
( FilenameFilter filter) 设置当前文件过滤器。