第一节 Java GUI编程的基础知识
java的GUI编程(Graphic User Interface,图形用户接口),是在它的抽象窗口工具箱(Abstract Window Toolkit,AWT)上实现的,java.awt是AWT的工具类库,其中包括了丰富的图形、用户界面元件和布局管理器的支持。
GUI主要用在两个地方:
Application;
Applet。
1)GUI界面:
用户与程序之间交互的一个控制面板,其内包含有菜单,控件(或组件),容器并能响应用户的事件。
现在有各种各样的窗口系统,不同的窗口系统提供给程序设计的程序库是大不一样的,例如,基于Windows的SDK,和基于Unix平台的X Windows的Xlib。
为了使程序能在不同的窗口系统下运行,Java提出了“抽象窗口系统”的概念,提供了AWT(抽象窗口工具箱),使得java能够在不同的窗口系统下运行。
2)Java中的GUI实现方式:
采用AWT(抽象窗口工具集)从而可使GUI适用于不同OS的环境。
特点如下:
① 其具体实现由目标平台下的OS来解释,从而导致Java GUI在不同平台下会出现不同的运行效果(窗口外观、字体等的显示效果会发生变化)。
② 组件在设计时不应采用绝对定位,而应采用布局管理器来实现相对定位,以达到与平台及设备无关。
3)新增的Swing GUI组件
AWT组件以及事件响应不及微软的SDK丰富(因为有些OS平台无微软的Windows组件),Sun在Java2中新增了Swing GUI组件。但是,AWT比较简单,功能也能满足大多数界面需求,特别在Java Applet的设计中受到了普遍的应用。同时,这个讨论也为我们进一步研究Swing GUI组件打下了比较扎实的基础。
第二节 用户界面基本设计
一、 Java AWT中组件种类:
(1)基本组件
它不能独立地显示出来并且在其内不能再包含其它的组件(如Button、Checkbox、 Choice、Canvas、Label、TextField、TextArea、List、Scrollbar等是AWT中的基本组件)。
(2)容器组件(Container类)
包含其它基本组件或子容器的组件,并由布局管理器统一决定其内的各个组件的摆放位置和大小(Frame窗框、Dialog对话框、Panel面板、FileDialog文件对话框等)。
①Panel和 Applet是无边框的容器组件。
②ScrollPane是具有边框且带有滚动条的容器组件
③Window、Frame、Dialog、FileDialog等都是有边框的容器组件并且可以移动、放大、缩小、关闭等。
(3)菜单条式菜单组件:
MenuBar菜单条组件、Menu级联菜单组件、MenuItem菜单项组件、CheckboxMenuItem选择性菜单组件。
(4)弹出式菜单组件:
PopupMenu(可以右击或触发其它组件弹出它)。
二、各个组件的常用方法
1)Component类:
提供了一系列被一般组件所广泛用到的方法
getBounds( ) and setBounds( )
getBackground (), setBackground( ), getForeground( ), and setForeground( ) getEnabled( ) and setEnabled( )
getFont( ) and setFont( )
getParent( )
getSize( ), setSize( ), getPreferredSize( ), and setPreferredSize( )
setVisible( )
2)Label
构建函数: Label( ), Label(String text),Label(String text, int alignment)
方法:getText( ),setText(String text)
3)Button
构建函数: Button( ),Button(String label)
方法:getLabel( ),setLabel(String label)
4)TextField
构建函数: TextField(),TextField(int columns), TextField(String text),TextField(String text, int columns)
方法:getColumns(),setColumns(int columns) ,setText(String text)
5)TextArea
构建函数: TextArea(), TextArea(int rows, int columns), TextArea(String text),
TextArea(String text, int rows, int columns)
TextArea(String text, int rows, int columns, int scrollbars)
这里scrollbars可以是:
SCROLLBARS_BOTH,
SCROLLBARS_NONE,
SCROLLBARS_VERTICAL_ONLY
或 SCROLLBARS_HORIZONTAL_ONLY
方法:getRows(), getColumns(), setRows(), setColumns(), insert(String str, int position) , append(String str)
6)Checkbox
构建函数: Checkbox(), Checkbox(String label), Checkbox(String label, boolean state),
Checkbox(String label, boolean state, CheckboxGroup group),
Checkbox(String label, CheckboxGroup group, boolean state),
7)List
构建函数: List (),List (int rows),List (int rows, boolean multipleMode)
8)Choice
构建函数: Choice()
方法:add (String item),addItem (String item),select (int position
select (String str)
9)Scrollbar
构建函数: Scrollbar (), Scrollbar (int orientation),
Scrollbar (int orientation, int value, int visible, int minimum)
10)Canvas
构建函数: Canvas(), Canvas(GraphicsConfiguration config)
11)Containers:定义了一系列所有容器都要用到的方法
add( ) – 加入一个元件到容器
getComponent( ) and getComponentAt( ) – 获得一个组件的容器
getInsets( ) –返回容器边界的信息
remove( ) and removeAll( ) –移除容器的构成
getLayout( ) and setLayout( ) –获取和设置容器元件排列的方式
validate( ) and validateTree( ) – 引发容器重新显示
12)Window
方法:pack( ),setSize( ),show( ),toFront( ) and toBack( ),dispose( )
13)Frame
构建函数: Frame( ) and Frame(String title)
创建一个Frame时,它的缺省状态为不显示,而且大小为0
所以创建一个Frame后应当:
Frame f = new Frame(“Hello, there”);
f.setSize(100, 120); // 100 is width, 120 is height
f.setBackground(Color.blue);
f.setVisible(true); // display the frame
14)Dialog:一个可跳出的对话窗口
15)FileDialog:一个文件操作的窗口
16)Panel:面板,用以放其他组件,缺省状态为不可见。
Applet
ScrollPane:带滚动条的Panel
MenuComponent:定义了一般菜单组件的特性和行为
getFont( ) and setFont( ),getName( ) and setName( ),getParent( )
MenuBar:每一个Frame只可以有一个MenuBar,MenuBar用以容纳其他菜单组件。Frame有一个setMenuBar(MenuBar,mb ) 的方法
MenuItem
方法:getLabel( ), setLabel( ), setShortcut( ), setShortcut( ), isEnabled( ) and setEnabled( )
Menu
方法:add( ), insert( ), remove( ), removeAll( ), getItem( ) getItemCount( )
CheckboxMenuItem
方法:getState( ) and setState( )
PopupMenu
三、Java GUI编程的主要工作:
(1)设计并创建出组成用户界面的各个组件并布局它们在容器内的位置和大小。
(2)设计出各个组件的事件并编程事件,从而对不同的事件加以响应。
四、组件的基本设计方法:
(一)、基本组件的创建:
1、在init( )(对Java Applet而言)或Frame的构造函数内(对Java Application而言)创建出各个组件对象并初始化其外观、状态等属性。
2、调用容器的add( )分别将创建出的各个组件加入到Applet或Frame所在的容器中;然后注册其事件监听器对象。
(二)、容器组件的创建:
1、在init( ) 或Frame的构造函数中内,首先创建出容器组件对象并实例化它,设置布局方式。
2、分别创建出在容器内待包含的各个基本组件并实例化它们。
3、调用容器内的add( )函数将各个基本组件加入到容器内。
4、再调用add( )将各个子容器加入到Applet中或Frame的主窗框中;然后注册各个基本组件和容器的事件监听器对象。
5、对Frame容器则需要调用setVisible(true)调显示出其内的各个组件,而对Dialog容器则需要调用Dialog.show()显示出其内的各个组件。
首先我们做一个框架,作为以后样例的基础:
package myguipack;
import java.awt.*;
import java.awt.event.*;
import java.*;
import java.lang.*;
public class myguiDemo extends Frame {
//构造函数
public myguiDemo() {
jbInit();
}
//开始代码
public static void main(String[] args) {
myguiDemo frame = new myguiDemo();
//设置窗口的标题,大小与布局
frame.setTitle("事件加入的程序演示");
frame.setSize(300, 200);
//显示元件
frame.setVisible(true);
}
//初始化代码
private void jbInit()
{
//激活Windows事件
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
}
//这是检测退出程序的的事件,没有这个事件窗口将无法关闭
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
这里需要注意一个问题,当利用Frame主窗框的关闭按钮关闭窗口的时候,不会自动关闭,所以需要加入一个Close事件的处理,可以利用程序中写的那样,也可以用如下的Frame主窗框事件编程WINDOWCLOSING(用户正在关闭窗口时产生,如用户单击窗口上关闭按钮时)。利用此事件可以达到关闭应用程序的窗口
public void windowClosing(WindowEvent event)
{ dispose(); //关闭应用程序的窗口
System.exit(0); //进程退出
}
样例:
package demo;
import java.awt.*;
import java.awt.event.*;
import java.*;
import java.lang.*;
public class GuiDemo extends Frame {
//构造函数的参数为长度
TextField jTextField1 = new TextField(30);
Button jButton1 = new Button();
Button jButton2 = new Button();
Button jButton3 = new Button();
//构造函数
public GuiDemo() {
jbInit();
}
//开始代码
public static void main(String[] args) {
GuiDemo frame = new GuiDemo();
//显示元件
frame.setVisible(true);
}
//初始化代码
private void jbInit()
{
//激活Windows事件
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
//设置窗口的标题,大小与布局
setTitle("元件加入的程序演示");
setSize(new Dimension(300, 100));
//从上到下,从左到右依次摆放,每行均居中
this.setLayout(new FlowLayout());
jTextField1.setText("我的实验");
jButton1.setLabel("查询");
jButton2.setLabel("删除");
jButton3.setLabel("添加");
//加入容器
this.add(jTextField1);
this.add(jButton1);
this.add(jButton2);
this.add(jButton3);
}
//这是检测退出程序的的事件,没有这个事件窗口将无法关闭
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
(三)容器组件的布局
(1) 布局:
决定容器内的各个组件的摆放状态(组件大小及相对位置等),它由布局管理器来控制。
(2) Java.awt包中布局种类(五种):
(3)使用指定的布局方式:创建指定布局方式类的对象,然后调用容器类的setLayout()方法来指定所需的布局方式。setLayout(new FlowLayout());
要点:Java中不希望采用绝对定位布局而采用相对定位布局,如需要使用绝对定位布局,则应该取消容器的布局方式(setLayout(null)),然后使用 setLocation() setSize() setBounds()设置组件的大小及位置。
下面分别对五种布局方式的编程加以说明。
Flowlayout
从上到下,从左到右依次摆放,每行均居中,它是Panel、Applet的缺省布局。
实例为上面的例子。
BorderLayout
将容器内的空间划分为东、南、西、北、中五个方位,并指明组件所在的方位,它是Window、Dialog、Frame的缺省布局方式。
实例:
package demo;
import java.awt.*;
import java.awt.event.*;
import java.*;
import java.lang.*;
public class GuiDemo extends Frame {
//构造函数的参数为长度
TextField jTextField1 = new TextField(30);
Button jButton1 = new Button();
Button jButton2 = new Button();
Button jButton3 = new Button();
Button jButton4 = new Button();
//构造函数
public GuiDemo() {
jbInit();
}
//开始代码
public static void main(String[] args) {
GuiDemo frame = new GuiDemo();
//显示元件
frame.setVisible(true);
}
//初始化代码
private void jbInit()
{
//激活Windows事件
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
//设置窗口的标题,大小与布局
setTitle("元件加入的程序演示");
setSize(new Dimension(300, 200));
//布局
this.setLayout(new BorderLayout());
jTextField1.setText("中");
jButton1.setLabel("东");
jButton2.setLabel("南");
jButton3.setLabel("西");
jButton4.setLabel("北");
//加入容器,并赋予它所处的位置
this.add(jTextField1,BorderLayout.CENTER);
this.add(jButton1,BorderLayout.EAST);
this.add(jButton2,BorderLayout.SOUTH);
this.add(jButton3,BorderLayout.WEST);
this.add(jButton4,BorderLayout.NORTH);
}
//这是检测退出程序的的事件,没有这个事件窗口将无法关闭
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
GridLayout
行列网格状布局。
这种布局方式首先放一个容纳单元的栅格,元件放到这个网格的单元个中,GridLayout构造方法:
GridLayout(int row,int col)
GridLayout(int row,int col,int hGap,int vGap)
其中:row:行数
col: 列数
如果某个值为零,表示这个方向可以任意扩展。
HGap、vGap表示以象素为单位的元件间隔。
元件总是充满单元格,而且随着边框的变化而变化。
样例:
package demo;
import java.awt.*;
import java.awt.event.*;
import java.*;
import java.lang.*;
public class GuiDemo extends Frame {
//构造函数的参数为长度
TextField jTextField1 = new TextField(30);
Button jButton1 = new Button();
Button jButton2 = new Button();
Button jButton3 = new Button();
Button jButton4 = new Button();
//构造函数
public GuiDemo() {
jbInit();
}
//开始代码
public static void main(String[] args) {
GuiDemo frame = new GuiDemo();
//显示元件
frame.setVisible(true);
}
//初始化代码
private void jbInit()
{
//激活Windows事件
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
//设置窗口的标题,大小与布局
setTitle("元件加入的程序演示");
setSize(new Dimension(300, 200));
//布局
this.setLayout(new GridLayout(0,2,10,10));
jTextField1.setText("中");
jButton1.setLabel("东");
jButton2.setLabel("南");
jButton3.setLabel("西");
jButton4.setLabel("北");
//加入容器,并赋予它所处的位置
this.add(jTextField1);
this.add(jButton1);
this.add(jButton2);
this.add(jButton3);
this.add(jButton4);
}
//这是检测退出程序的的事件,没有这个事件窗口将无法关闭
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
CardLayout
卡片叠式布局。
这种布局方式,可以用来管理两个或者更多共享同一显示区域的元件。它具有以下两个构造方法:
CardLayout()
CardLayout(int hGap,int vGap)
样例:
package demo;
import java.awt.*;
import java.awt.event.*;
import java.*;
import java.lang.*;
public class GuiDemo extends Frame {
//构造一个容器,放置可变的元件
Panel cardContainer=new Panel();
//构造函数的参数为长度
TextField jTextField1 = new TextField(30);
Button jButton1 = new Button();
Button jButton2 = new Button();
Button jButton3 = new Button();
//列表框
Choice c=new Choice();
String ca1="按钮";
String ca2="正文域";
//构造函数
public GuiDemo() {
jbInit();
}
//开始代码
public static void main(String[] args) {
GuiDemo frame = new GuiDemo();
//显示元件
frame.setVisible(true);
}
//初始化代码,这里踢出了错误
private void jbInit()
{
//激活Windows事件
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
//设置窗口的标题,大小与布局
setTitle("元件加入的程序演示");
setSize(new Dimension(300, 200));
//所有的元件都按顺序方式布局
this.setLayout(new BorderLayout(0,3));
jTextField1.setText("您好");
jButton1.setLabel("按钮1-1");
jButton2.setLabel("按钮1-2");
jButton3.setLabel("按钮1-3");
//列表框赋初值
c.add(ca1);
c.add(ca2);
//构造下拉列表改变的事件侦听器
c.addItemListener(new java.awt.event.ItemListener()
{
public void itemStateChanged(ItemEvent e)
{myItem(e);}
}
);
//构造一个容器放列表框
Panel globarPanel=new Panel();
globarPanel.add(c);
this.add("North",globarPanel);
//cardContainer按CardLayout布局
cardContainer.setLayout(new CardLayout());
Panel p1=new Panel();
p1.add(jButton1);
p1.add(jButton2);
p1.add(jButton3);
Panel p2=new Panel();
p2.add(jTextField1);
//把两个容器都加入
cardContainer.add(ca1,p1);
cardContainer.add(ca2,p2);
this.add("Center",cardContainer);
/*
实际上,用下面的代码可以分别显示两种布局
但这里是使用了事件
((CardLayout)cardContainer.getLayout()).show(
cardContainer,ca1);
((CardLayout)cardContainer.getLayout()).show(
cardContainer,ca2);
*/
}
//这是下拉列表改变的事件程序
void myItem(ItemEvent e)
{
((CardLayout)cardContainer.getLayout()).show(
cardContainer,(String)e.getItem());
}
//这是检测退出程序的的事件,没有这个事件窗口将无法关闭
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
GridBayLayout
自定义网格状布局。
样例:
package demo;
import java.awt.*;
import java.awt.event.*;
import java.*;
import java.lang.*;
public class GuiDemo extends Frame {
//构造函数
public GuiDemo() {
jbInit();
}
//开始代码
public static void main(String[] args) {
GuiDemo frame = new GuiDemo();
frame.setTitle("元件加入的程序演示");
frame.setSize(300,200);
//显示元件
frame.setVisible(true);
}
public void makebutton(
String name,
GridBagLayout gridbag,
GridBagConstraints c)
{
Button button=new Button(name);
gridbag.setConstraints(button,c);
this.add(button);
}
//初始化代码
private void jbInit()
{
//激活Windows事件
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
GridBagLayout gridbag=new GridBagLayout();
GridBagConstraints c=new GridBagConstraints();
this.setFont(new Font("宋体",Font.PLAIN,11));
this.setLayout(gridbag);
c.fill=GridBagConstraints.BOTH;
c.weightx=1.0;
makebutton("Bt1",gridbag,c);
makebutton("Bt2",gridbag,c);
makebutton("Bt3",gridbag,c);
c.gridwidth=GridBagConstraints.REMAINDER;
makebutton("Bt4",gridbag,c);
c.weightx=0.0;
makebutton("Bt5",gridbag,c);
c.gridwidth=GridBagConstraints.RELATIVE;
makebutton("Bt6",gridbag,c);
c.gridwidth=GridBagConstraints.REMAINDER;
makebutton("Bt7",gridbag,c);
c.gridwidth=1;
c.gridheight=2;
c.weighty=1.0;
makebutton("Bt8",gridbag,c);
c.weighty=0.0;
c.gridwidth=GridBagConstraints.REMAINDER;
c.gridheight=1;
makebutton("Bt9",gridbag,c);
makebutton("Bt10",gridbag,c);
}
//这是检测退出程序的的事件,没有这个事件窗口将无法关闭
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
手动布局
样例:
package demo;
import java.awt.*;
import java.awt.event.*;
import java.*;
import java.lang.*;
public class GuiDemo extends Frame {
//构造函数的参数为长度
TextField jTextField1 = new TextField(30);
Button jButton1 = new Button();
//构造函数
public GuiDemo() {
jbInit();
}
//开始代码
public static void main(String[] args) {
GuiDemo frame = new GuiDemo();
//显示元件
frame.setVisible(true);
}
//初始化代码
private void jbInit()
{
//激活Windows事件
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
//设置窗口的标题,大小与布局
setTitle("元件加入的程序演示");
setSize(new Dimension(300, 100));
//从上到下,从左到右依次摆放,每行均居中
this.setLayout(null);
jTextField1.setText("我的实验");
jTextField1.setBounds(new Rectangle(20, 40, 120, 20));
jButton1.setLabel("查询");
jButton1.setBounds(new Rectangle(180, 40, 97, 23));
//加入容器
this.add(jTextField1);
this.add(jButton1);
}
//这是检测退出程序的的事件,没有这个事件窗口将无法关闭
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}