如何开发JAVA的GUI程序

一、java的GUI编程(Graphic User Interface,图形用户接口),是在它的抽象窗口工具箱AWT/SWING/SWT上实现的,其中包括了丰富的图形、用户界面元件和布局管理器的支持。
GUI主要用在两个地方:Application;Applet。

二、JAVA程序的GUI技术的发展
当Java在1995年的春天第一次发布的时候,它包含了一个叫AWT(Abstract Windowing Toolkit)的库,用来构建图形用户界面应用程序。Java很有雄心的宣言--"write once, run anywhere"许诺。AWT的缺省实现使用了"对等"机制,即每一个Java GUI窗口部件都在底层的窗口系统中有一个对应的组件。Java不得不妥协和折衷。特别的,Java采用了"最小公分母"的方法,即AWT仅仅提供所有本地窗口系统都提供的特性。
于1997年JavaOne大会上提出并在1998年5月发布的JFC(Java Foundation Classes)包含了一个新的使用Java窗口开发包。这个新的GUI组件叫做Swing,感觉到它是对AWT的升级,并且看起来对Java占据计算机世界很有帮助。 AWT依赖对等架构,用Java代码包装本地窗口部件,Swing却根本不使用本地代码和本地窗口部件。AWT把绘制屏幕交给本地窗口部件,Swing自己的组件绘制自己。SWING有两方面的缺点:速度的缺乏,界面外观。
当Eclipse.org社区人员开始构建Eclipse时,他们意识到Swing和AWT都不足以用来构建真实世界的商业程序。结果,他们决定构建一套新的GUI开发工具包用来显示Eclipse界面。他们把这个新的工具包命名为SWT(Standard Widget Toolkit).意识到本地行为需要本地窗口部件,SWT的设计者们采用了AWT的对等架构,而仅仅当本地组件不存在时(例如Motif下的树形组件)才求助于Java实现。

三、AWT,SWING,SWT选择哪一个?
AWT的优势在于,简单,稳定,兼容于任何一个java版本。也支持GUI组件的自动disposal。同时也是线程安全的。在AWT 中的图形用户界面是通过本地方法来实现的,每个AWT 方法都有一个与其对应的本地方法,称为peer。由于平台无关性的需要,AWT 所能够实现的功能是各种不同操作系统的图形库所提供的功能的交集。
而SWING,则是为了解决AWT的很多缺点。SWING 提供许多比AWT更好的屏幕显示元素。它们用纯Java写成,所以同Java本身一样可以跨平台运行,这一点不像AWT。 它们是JFC的一部分。 它们支持可更换的观感和主题(各种操作系统默认的特有主题),然而不是真的使用原生平台提供的设备,而是仅仅在表面上模仿它们。这意味着你可以在任意平台上使用JAVA支持的任意观感。 轻量级元件的缺点则是执行速度较慢,优点就是可以在所有平台上采用统一的行为。
Eclipse项目用称为SWT的的图形库和工具包取代了Java标准中的AWT和Swing。SWT直接调用了操作系统的图形库,从而使得Java应用程序的Look & Feel 与操作系统的习惯完全一致;更为重要的是,对本地方法的直接调用大幅度的提高了基于SWT 的Java应用程序的运行速度。SWT 的缺点主要在于两点:(1) 不是Java语言标准;和(2) 支持的平台太少。

四、Java GUI编程中的事件处理机制。

Java中的事件主要有两种:

1.组件类事件

componentEvent、ContainerEvent、WindowEvent、FocusEvent、PaintEvent、MouseEvent共六大类,

它们均是当组件的状态发生变化时产生。

2.动作类事件

ActionEvent、TextEvent、AdjustmentEvent、ItemEvent共四类。

Java中的事件类都包含在JDK的 Java.awt.event包中。

3、事件编程的基本规则:

(1)组件对事件的响应形式:忽略它(本类不实现对应的监听器接口)或编程事件函数以处理它(可根据应用需要替换某一个组件的相应缺省事件处理函数,从而响应用户对该组件的操作。本类实现某类事件对应的监听器接口,并实现对应的响应函数),也可屏蔽它(将其事件响应函数体置空)。

(2)事件响应类(监听器)可以实现多个监听器接口,以响应多组不同事件,从而可使同一个组件可以注册多种事件。

(3)利用事件响应函数中的事件对象获取事件产生时的相关信息(event.getSource())事件源对象,event.getX(), event.getY(),事件产生时的鼠标位置,event.getActionCommand(),获取组件的字符串名称。

4、各个事件监听器接口

ActionListener

使用它的常见AWT类 Button, List, TextField

接口定义的方法

public void actionPerformed(ActionEvent e)

添加到组件的方法

Obj.addActionListener(ActionListener l)

AdjustmentListner

使用它的常见AWT类 ScrollBar

接口定义的方法

public void adjustmentValueChanged(AdjustmentEvent e)

添加到组件的方法

Obj.addAdjustmentListener(AdjustmentListener l)

ComponentListener

使用它的常见AWT类

接口定义的方法

public void componentResized(ComponentEvent e)

public void componentMoved(ComponentEvent e)

public void componentShown(ComponentEvent e)

public void componentHidden(ComponentEvent e)

添加到组件的方法

Obj.addComponentListener(ComponentListener l)

ContainerListener

使用它的常见AWT类

接口定义的方法

public void componentAdded(ContainerEvent e)

public void componentRemoved(ContainerEvent e)

添加到组件的方法

ItemListener

使用它的常见AWT类 Checkbox, Choice, List

接口定义的方法

public void itemStateChanged(ItemEvent e)

添加到组件的方法

FocusListener

使用它的常见AWT类

接口定义的方法

public void focusGained(FocusEvent e)

public void focusLost(FocusEvent e)

添加到组件的方法

KeyListener

使用它的常见AWT类

接口定义的方法

public void keyTyped(KeyEvent e)

public void keyPressed(KeyEvent e)public void keyReleased(KeyEvent e)

添加到组件的方法

MouseListener

使用它的常见AWT类

接口定义的方法

public void mouseClicked(MouseEvent e)

public void mousePressed(MouseEvent e)

public void mouseReleased(MouseEvent e)

public void mouseEntered(MouseEvent e)

public void mouseExited(MouseEvent e)

添加到组件的方法

MouseMotionListener

使用它的常见AWT类

接口定义的方法

public void mouseDragged(MouseEvent e)

public void mouseMoved(MouseEvent e)

添加到组件的方法

TextListener

使用它的常见AWT类 TextField, TextArea

接口定义的方法

public void textValueChanged(TextEvent e)

添加到组件的方法

WindowListener

使用它的常见AWT类

接口定义的方法

public void windowOpened(WindowEvent e)

public void windowClosing(WindowEvent e)

public void windowClosed(WindowEvent e)

public void windowIconified(WindowEvent e)

public void windowDeiconified(WindowEvent e)

public void windowActivated(WindowEvent e)

public void windowDeactivated(WindowEvent e)

添加到组件的方法

4、事件适配器

由于事件监听器接口是Abstract类型,意谓着实现该接口的类应全部实现其各个成员函数,但实际应用中可能只需处理某些事件响应代码;此时再采用实现事件监听器接口可能会导致编程复杂。JDK中提供事件适配器方式来实现事件编程。

①每一种监听器接口有相应的适配器类,程序员只需让事件处理类从某一适配器类派出而不采用实现监听器接口的方式,这样仅需重写用户感兴趣的相应函数体代码。各个事件监听器接口相相应的事件适配器类如下:

WindowListener ------WindowAdapter

MouseListener -----MouseAdapter

MouseMotionListener-----MouseMotionAdapter。

②在事件注册时,应将监听器设为适配器的派生类(子类)对象,该适配器类中事件响应函数将被执行

5、两个简单的例子
1).事件处理

public class ButtonActionEvent extends Applet
implements ActionListener,MouseMotionListener,MouseListener
{
public void init()
{ this.addActionListener(this);
this.addMouserMotionListener(this);
this.addMouseListener(this);
}
public void actionPerFormed(ActionEvent event)
{
if(event.getSource()==SourceObject)
{ //利用事件响应函数中的事件对象获取事件产生时的相关信息
}
else if(event.getActionCommand()=="组件的标签名字符文字"
{
}
}
public void mouseDragged(MouseEvent event)
{ //利用事件响应函数中的事件对象获取事件产生时的相关信息
int x=event.getX();
int y=event.getY();
}
public void mouseMove(MouseEvent event)
{
}
}
2)、界面建立加事件处理
import javax.swing.*;
import java.awt.event.*;public class TestButtons {
 JFrame frame = new JFrame("Test Buttons");
 JButton jButton = new JButton("JButton"); //按钮
 JToggleButton toggle = new JToggleButton("Toggle Button"); //切换按钮
 JCheckBox checkBox = new JCheckBox("Check Box"); //复选按钮
 JRadioButton radio1 = new JRadioButton("Radio Button 1"); //单选按钮
 JRadioButton radio2 = new JRadioButton("Radio Button 2");
 JRadioButton radio3 = new JRadioButton("Radio Button 3");
 JLabel label = new JLabel("Here is Status, look here."); //不是按钮,是静态文本 public TestButtons() {
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.getContentPane().setLayout(new java.awt.FlowLayout());  
  jButton.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
   label.setText("You clicked jButton");
  }
 }); 
 toggle.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
   JToggleButton toggle = (JToggleButton) ae.getSource();
   if (toggle.isSelected()) {
    label.setText("You selected Toggle Button");
   } else {
    label.setText("You deselected Toggle Button");
   }
  }
 }); 
 checkBox.addItemListener(new ItemListener() {
 public void itemStateChanged(ItemEvent e) {
  JCheckBox cb = (JCheckBox) e.getSource();
  label.setText("Selected Check Box is " + cb.isSelected());
 }
}); 
 ButtonGroup group = new ButtonGroup();
 
 ActionListener al = new ActionListener() {
 public void actionPerformed(ActionEvent ae) {
  JRadioButton radio = (JRadioButton) ae.getSource();
  if (radio == radio1) {
   label.setText("You selected Radio Button 1");
  } else if (radio == radio2) {
   label.setText("You selected Radio Button 2");
  } else {
   label.setText("You selected Radio Button 3");
  }
 }
};
 
 radio1.addActionListener(al);
 radio2.addActionListener(al);
 radio3.addActionListener(al);
 
 group.add(radio1); group.add(radio2);
 group.add(radio3); frame.getContentPane().add(jButton);
 frame.getContentPane().add(toggle);
 frame.getContentPane().add(checkBox);
 frame.getContentPane().add(radio1);
 frame.getContentPane().add(radio2);
 frame.getContentPane().add(radio3);
 frame.getContentPane().add(label); frame.setSize(200, 250);
} public void show() {
  frame.show();
 } public static void main(String[] args) {
  TestButtons tb = new TestButtons();
  tb.show();
 }

事件处理程序显然,在此不做进一步的说明。
界面建立加事件处理可能大家有点晕,下面加以说明。该程序一共部分。前面是类成员变量说明和初始化,接下来是TestButtons()函数,接下来是show() 函数,最后是 main()主函数。复杂的是TestButtons()的几个内嵌类。例如:

jButton.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
   label.setText("You clicked jButton");
  }
 });
ActionListener() {
  public void actionPerformed(ActionEvent ae) {
   label.setText("You clicked jButton");
  }


 }是以内嵌类。

本文是笔者的《JAVA语言程序设计》一书的补遗,也是作者多年的一个遗愿。《JAVA语言程序设计》出版的 时候尚没有SWING和SWT,界面的编程受到了多种操作系统平台最大公共集的限制,现在不光有了SWING,还有了SWT。还有了功能强大的事件处理接口。本文不足以反映JAVA语言程序界面设计的全面进展,今后陆续推出更多的关于JAVA语言程序设计的文章。《JAVA语言程序设计》让我回忆起自己在清华读研究生的生活,毕竟那是我生活的一部分。特写此文用以纪念那和那么多朋友一同度过的快乐时光。