Java图形用户界面设计之概述


前言

本文主要讲述java 的GUI概述:

Java的基础类(Java Foundation Classes,JFC)是开发GUI的API集,它包括以下几个部分:
AWT(抽象窗口工具包):Java开发图形用户界面最初的工具包,是建立JFC的主要基础;
Swing组件:建立在AWT之上,新的、功能更强大的图形组件包


一、GUI概述

(1)Java语言为了方便图形用户界面的开发,设计了专门的类库来生成各种标准图形界面和处理图形界面的各种事件, 这个类库就是java.awt包:

AWT是Abstract Window Toolkit(抽象窗口工具集)的缩写。
AWT类库中的各种操作被定义在一个并不存在的抽象窗口中进行,以实现跨平台性。
AWT抽取了不同软硬件平台中所实现的窗口的公共特性,所设计的界面独立于具体的界面实现 。
AWT提供与机器无关的基本GUI标准组件。

(2)AWT包含的构件太多,主要讨论以下几个最重要的类:

基本的窗口类:Frame,Dialog。
基本的GUI构件类:Button,Label,TextField,TextArea。
基本的事件接口:ActionListener,WindowListener,MouseListener,KeyListener。
基本的版面控制:FlowLayout,BorderLayout,GridLayout,Panel。
基本的绘图支持:Graphics,Canvas。

(3)Swing简介:

Swing 是AWT的扩展,是在AWT的基础上发展起来的一套新的图形界面系统,它提供了AWT 所能够提供的所有功能,并且用纯Java代码对AWT 的功能进行了大幅度的扩充。

Swing组件存放在javax.swing包中。几乎所有AWT组件对应有新功能更强的Swing组件。另外还加入了一些全新的组件。Swing组件在名称上前面多了一个字母“J”。

1.创建 GUI 的一般步骤:

(1)选择容器。
(2)确定布局。
(3)向容器中添加组件。
(4)进行事件处理。

(1)Component类

java.awt包中最核心的类,大部分控制组件都是由该类派生出来的,用于完成与用户的交互。
定义了组件所具有的一般功能:
基本的绘画支持(方法paint, repaint, update等)
字体和颜色等外形控制(方法setFont, SetForeground等)
大小和位置控制(方法setSize, setLocation等)
图像处理(接口ImageObserver)
组件状态控制(方法SetEnable, isEnable, isVisible, isValid等)
常用的组件包括:Button, Checkbox, CheckboxGroup, Choice, Label, List, Canvas, TextComponent, Scrollbar等。

(2)Container类

是由Component类派生出来的一种特殊类,用来表示各种GUI组件的容器。
通常,一个图形用户界面程序首先对应于一个容器,这个容器再进一步包括其它的界面成分和元素,以构成一个复杂的图形界面系统
Container类主要功能包括:
组件的管理:如方法add()可以向其中添加一个组件,remove()删除其中的一个组件,…
布局管理:每个Container类都和一个布局管理器相联,以确定其中组件的布局。Container类可以通过setLayout()方法设置某种布局方式。
常见的Container类有:Window, Frame, Panel, Applet等。
在这里插入图片描述

(3)Window类

表示一个没有边界和菜单的最高层的窗口,可以包含AWT的其他构件。初始化时,窗口是不可见的。
在这里插入图片描述

(4)Frame 类

一个Frame是包括标题、菜单、文本区和按钮的图形窗口,其外观依赖于所使用的的操作系统。Frame包含在一个方框内,其大小可以伸缩。
在这里插入图片描述

例:建立一个Frame对象,并使之可见。

import java.awt.Frame;
public class MyFrameTest{
    public static void main(String args[ ]){
        Frame myFrame = new Frame("My First Frame");
        myFrame.setVisible();     //使一个Frame可见
	       myFrame.setSize(100,200); 
    }
}          

注:当这个程序执行时,会出现一个带标题的小窗口,这个窗口可以伸缩并且包含有标准的关闭按钮。但目前这个窗口还没有响应关闭按钮的能力,因此可以打开任务管理器关闭这个任务

创建GUI的一般步骤:

(1)选择容器。
(2)确定布局。
(3)向容器中添加组件。
(4)进行事件处理。

容器与布局

组件:是可以用图形化的方式显示在屏幕上并能够与用户进行交互的对象。
容器:在进行图形用户界面设计的时候,GUI的各个组件需要放置在容器(Container)中进行管理。容器是一种特殊的组件,一种能够容纳其他组件或容器的组件。
布局:在设计图形用户界面时,必须决定界面中的各个组件如何摆放并展示给用户。为了使图形用户界面具有良好的平台无关性,提供了专门用来管理组件在容器中的布局的工具。

布局管理器

Java语言提供了布局管理器来管理组件在容器中的布局,而不直接设置组件的位置和大小。每个容器都要一个布局管理器,容器中组件的定位都由它来决定。当容器需要对某个组件进行定位时,就会调用其对应的布局管理器。

Java中提供了各种布局管理器类来管理各种组件在容器中的放置状态,这些类都是实现了LayoutManager接口。

标准的布局管理器类有:
FlowLayout BorderLayout GridLayout
CardLayout GridBagLayout

在程序中安排组件的位置和大小时,应注意:

容器中布局管理器负责各组件的大小和位置,用户无法在这种情况下设置组件的这些属性,如试图调用setLocation(), setSize(), setBounds()等。
如果用户确实需要自己设置组件的大小和位置,则应取消该容器的布局管理器,方法为:
setLayout(null)
但用户必须使用setLocation(), setSize(), setBounds()等方法为组件设置大小和位置,不过此时程序与系统相关。

在容器中所有组件的布局都由布局管理器来控制,每个容器,都有各自缺省的布局管理器:
FlowLayout:是Panel和Applet的缺省布局管理。
BorderLayout:是Window、Dialog和Frame的缺省布局管理器。
也可以根据需要指定一个新的布局管理器。

(1)FlowLayout

FlowLayout布局方式是将组件一排一排地依次放置,它自动调用组件的getPreferredSize( )方法,使用组件的最佳尺寸来显示组件。
当容器被重新设置大小后,则布局也会随之发生改变,各组件的大小不变,但相对位置会发生变化。

FlowLayout类有三种构造方法:
public FlowLayout()
使用缺省居中对齐方式,组件间的水平和竖直间距为缺省值5个象素。
public FlowLayout(int alignment)
使用指定的对齐方式
(FlowLayout.LEFT,FlowLayout.RIGHT,FlowLayout.Center)
水平和竖直间距为缺省值5象素。

public FlowLayout(int alignment, int horizontalGap, int verticalGap)

使用指定的对齐方式,水平和竖直间距也为指定值。

(2)FlowLayout布局程序示例

import java.awt.*;
public class lx extends Frame
{
	public lx() {
		super("ls s");
		setSize(500,300);
		setLayout(new FlowLayout());
		add(new Button("B2"));
		add(new Button("B3"));
		add(new Button("B4"));
		add(new Button("B5"));
		setVisible(true);
	}
	public static void main(String args[])
	{
		lx x=new lx();
	}
}

在这里插入图片描述

(3) BorderLayout

BorderLayout布局方式提供了更复杂的布局控制方法,它包括5个区域:North, South, East, West和Center,其方位依据上北下南左西右东。

当容器的尺寸发生变化时,各组件的相对位置不变,但中间部分组件的尺寸会发生变化,南北组件的高度不变,东西组件的宽度不变。

BorderLayout类有二种常用的构造方法:
public BorderLayout()
各组件间的水平和竖直间距为缺省值0个象素。

public BorderLayout( int horizontalGap, int verticalGap )
各组件间的水平和竖直间距为指定值。

(4)BorderLayout布局程序示例:

import java.awt.*;
public class ShowBorder extends Frame{
	public ShowBorder()
	{
	super("BoderLayout example");
	setLayout(new BorderLayout());
	add("East",new Button("东"));
	add("West",new Button("西"));
	add("North",new Button("北"));
	add(new Button("中"));
	add("South",new Button("南"));
	pack();setVisible(true);
	
	}
	public static void main(String args[])
	{
		ShowBorder b1= new ShowBorder();
	}
	

}

在这里插入图片描述
如果容器使用BorderLayout布局方式,则用add()方法往容器中添加组件时应指明添加的位置,如:
add(“West”, new Button(“West”));
add(“North”, new Button(“North”));
add(new Button(“West”), BorderLayout.SOUTH);
若没有指明放置位置,则表明为默认的“Center”方位。
每个区域只能添加一个组件,若添加多个,则只能显示最后一个。如果想在一个区域添加多个组件,则必须先在该区域放一个容器,再将多个组件放在该容器中。
若东西南北中有若干个区域没有放置组件,则这些区域将不会有预留,而中间区域将置空。

(5)GridLayout

GridLayout布局方式可以使容器中的各组件呈网格状分布。容器中各组件的高度和宽度相同,当容器的尺寸发生变化时,各组件的相对位置不变,但各自的尺寸会发生变化。
各组件的排列方式为:从上到下,从左到右。
BorderLayout类相类似,如果想在一个网格单元中添加多个组件,则必须先在该网格单元放一个容器,再将多个组件放在该容器中。

GridLayout类有三种典型的构造方法:
public GridLayout()
在一行中放置所有的组件,各组件间的水平间距为0象素。
public GridLayout ( int rows, int cols )
生成一个rows行,cols列的管理器,能放置rows*cols个组件。rows或cols可以有一个为0。若rows为0,这表示每行放置cols个组件,根据具体组件数,可以有任意多行;若cols为0,这表示共有rows行,根据具体组件数,每行可以放置任意多个组件。
public GridLayout(int rows, int cols, int horizontalGap, int verticalGap )
各组件间的水平和竖直间距为指定值。

(6)GridLayout布局程序示例:

import java.awt.*;
import java.awt.event.*;
public class ShowGrid extends Frame{
	public ShowGrid()
	{
		super("GridLayout example");
		setLayout(new GridLayout());
		add(new Button("button 1"));
		add(new Button("button 2"));
		add(new Button("button 3"));
		add(new Button("button 4"));
		add(new Button("button 5"));
		add(new Button("button 6"));
		add(new Button("button 7"));
		addWindowListener(new windowCloser());
		pack();
		setVisible(true);
	}
	public static void main(String args[]){
	ShowGrid g1=new ShowGrid();
	}
	class windowCloser extends WindowAdapter{
		public void windoeClosering(WindowEvent we)
		{
			System.exit(0);
		}
		}
	}

在这里插入图片描述

(7) CardLayout

该布局方式可以帮助用户处理两个或更多的组件共享同一显示空间。共享空间的组件之间的关系就像一摞卡片一样,它们摞在一起,只有最上面的组件是可见的。
CardLayout可以像换卡片一样处理这些组件:为每张卡片定义一个名字,可按名字选卡片;可以按顺序向前或向后翻卡片;也可以直接选第一张或最后一张卡片。
CardLayout
public void show(Container parent, String name)
public void next(Container parent)
public void previous(Container parent)
public void first(Container parent)
public void last(Container parent)

其中,Container是拥有该CardLayout布局管理器的容器。

CardLayout类有二种构造方法:
public CardLayout()
组件距容器左右边界和上下边界的距离为缺省值0个像素。
public CardLayout(int horizontalGap, int verticalGap)
组件距容器左右边界和上下边界的距离为指定值。
与BorderLayout类和GridLayout类相类似,每张卡片中只能放置一个组件,如果想在一张卡片放置多个组件,则必须先在该卡片放一个容器,再将多个组件放在该容器中。
采用CardLayout布局方式时,向容器中添加组件时可以为组件取一个名字,以供更换显示组件时使用:
add(Component, String);

常用组件

(1)标签类(Label)

Label是一个单行非编辑文本构件,它包含一个要显示的字符串,多用于提示性文字,它不支持用户的输入。标签可以被程序修改,AWT对标签的定义是:
在这里插入图片描述

(2)面板类(Panel)

一个面板是一个可容纳其他构件的类属容器,一个面板可以享有自己的布局管理器,并且不同的面板可以使用另一个布局管理器将它们组合在一起,并容纳在一个Frame、Applet或其他面板之中。
面板类扩展Container并且继承它的所有方法。其中SetLayout()和add()是最常用的方法。
为了构造复杂的布局,可以创建一个或多个面板,并定义它们的布局管理器,然后按照不同的布局把构件加入到这些面板中,最后这些面板又可作为构件并按照一个总的布局来安排。

(3)例子

现在考虑下图所示的程序界面,试分析它可以使用哪些布局(仅使用了GridLayout,BorderLayout和FlowLayout 3种)进行管理。
在这里插入图片描述
A=单个构件(标记)
B , C = GridLayout
D=A和B构成的BorderLayout
E=C和D构成的BorderLayout
F=单个构件
G=两个按钮和两个标签构成的FlowLayout
整个框架(Frame)=E、F、G构成的BorderLayout
标题(A表示)和标签Sizes、Styles及Toppings(B表示)安排在两行的大小不同,这说明是要用Boderlayout将它们组合在一起(D框表示)。C和D的大小又不一样,所以,这又是用另一个BorderLayout将这些构件组合在一起(用E表示)。

(4)List

List是一个由顺序排列的项组成的列表,它有一个垂直滚动条,由用户控制上下滚动。当用户在List对象的某一项上点击时,可以产生一个动作事件,也可能选择多项来产生动作事件。
List类包含有很多非常有用的方法,下表列出了部分方法。
在这里插入图片描述

(5) TextField类

TextField是对一行文本进行编辑的一个构件。它用来接受用户的输入或显示可编辑的文本输出。
在这里插入图片描述

(6) TextArea类

一个TextArea提供了可编辑和不可编辑的文本空间,可以用于输入或输出多行文本。它拥有自己的水平和垂直的滚动条,并有特别的控制符来控制文本的格式,例如:\n插入一个新的行,\t插入一个tab字符。AWT对这个类的定义如下:
在这里插入图片描述

(7) 菜单类

也是一种组件,只不过菜单类并不是由一般的Component类派生的,而是从MenuComponent类继承得到的。

在这里插入图片描述
菜单条(MenuBar)
只能添加到Frame中(用setMenuBar()),作为添加菜单的容器。
菜单(Menu)
作为菜单项容器,显示并控制其中的菜单项,支持菜单嵌套。
菜单项(MenuItem)
操作的动作可以用ActionListener监听其事件ActionEvent。
复选框菜单项(CheckboxMenuItem)
操作的动作可以用ItemListener监听其事件(ItemEvent)。
弹出式菜单(PopupMenu)
与菜单相似,也是菜单项的容器。

与菜单相关的类:
在这里插入图片描述

(8) 对话框

对话框(Dialog)是一个Frame或另一个对话框拥有的窗口,如果它的父窗口消失,它也随之撤消。对话框扩充Window类,因而继承了Window的show和pack等方法。有两种类型的对话窗口:
模态对话框(Modal Dialog)
阻塞父对象的输入,并且必须在它的父对象再次获得输入之前,被关闭或自动消失。
非模态对话框(Non-Modal Dialog)
阻塞父对象的输入,它可以与父对象并存。除非特别声明,一般的对话框是非模态的。

事件处理

(1)事件

事件是可视化构件或用户接口构件产生的信息,Java类通过使用特殊的方法能够对它作出反应。所有的事件保存在系统级的事件队列中,可由事件响应方法对它们进行检索并作出响应。
事件分为如下两种类型:
低级事件
高级事件(语义事件)

低级事件:
表示低级输入或在屏幕上的可视构件窗口系统事件,这些事件描述为:
ComponentEvent(组件事件:组件尺寸的变化,移动)
ContainerEvent(容器事件:组件增加,移动)
WindowEvent(窗口事件:关闭窗口,窗口闭合,图标化)
FocusEvent(焦点事件:焦点的获得和丢失)
KeyEvent(键盘事件:键按下、释放)
MouseEvent(鼠标事件:鼠标单击,移动)

高级事件(语义事件)
包括接口构件产生的用户定义的信息,这些事件描述为:
ActionEvent(动作事件:按钮按下,TextField中按Enter键)
AdjustmentEvent(调节事件:在滚动条上移动滑块以调节数值)
ItemEvent(项目事件:选择项目,不选择项目)
TextEvent(文本事件,文本对象改变)

事件处理模型
将事件源(产生事件的组件)和对事件的具体处理(利用一种称为监听器[listener]的实体来对事件进行具体的处理)分开。
组件(事件源)都不处理自己的事件,而是将事件处理委托给一个或多个处理实体(监听器),这种事件处理模型称为事件的授权处理模型。
不同的类型事件,可以交由不同类型的监听器去处理。
在这里插入图片描述

(2)Java 的事件类

每个事件源可以产生多个特定类型的事件,所有事件都放在包java.awt.event中,这些事件都从java.util.EventObject而来,它是所有事件类的超类,它有两个主要的方法:
getSource( ) 获取一个特定的事件源
toString( ) 返回事件对象名的字符串
对于发生在组件上的事件,则由java.awt.event.AWTEvent派生。

java.awt.event中常用的事件类
在这里插入图片描述

(3)事件监听器(Event Listener)

事件源和监听器是委托事件模型的两部分。
Java提供了抽象的响应特定事件的“事件监听器”,它们在java.awt.event包中被定义为接口,每个构件可以通过调用addXXXListener(XXXListener l)方法使某个事件监听器来监听某个事件源。
当一个事件发生时,事件源调用监听器所定义的处理方法,并提供该事件对象作为它的参数。
在这里插入图片描述

(4)适配器类(Adapters)

当一个类实现某一个接口时,即使我们只对其中的一两个方法感兴趣,也必须实现该接口所声明的所有方法。
Java提供了一个使用事件监听器的简便方法,即使用适配器和内部类,可以仅实现我们所需要的方法。
适配器类可以作为事件监听器的超类使用。扩展的适配器类允许覆盖想要实现的特定方法,而其他未实现的方法则采用默认的方式实现。Java提供的适配器类有:
ComponentAdapter、ContainerAdapter、FocusAdapter、KeyAdapter、MouseAdapter、MoseMotionAdapter和WindowAdapter,这些类均可被继承作为事件监听器。
例如:通过适配器类处理事件。使用适配器类作为窗口事件的监听器,单击窗口的标准关闭按钮时程序退出。

import java.awt.*;
import java.awt.event.*;
public class ProgramWithAdapterListener extends Frame{
	
private WindowCloser listener= new WindowCloser();
public ProgramWithAdapterListener()
{
	addWindowListener(listener);
	setSize(200,200);
	setVisible(true);
	}
public static void main(String args[])
{
	ProgramWithAdapterListener p=new ProgramWithAdapterListener();
	
}
class WindowCloser extends WindowAdapter
{
	
	public void windowClosing(WindowEvent we)
	{
		System.out.println("要退出了");
		System.exit(0);
	}
	}
	}


在这里插入图片描述

(5)内部类

定义在一个类中的另一个类。
初始化一个匿名内部类可以使用new关键字,后面跟一个class类型的定义作为一个方法的输入参数:
someMethod(new ClassType([constructorInputList]) {
/定义的内部类,包括域和方法/
} )

重新实现上一个例子,使用匿名内部类实现。

import java.awt.*;
import java.awt.event.*;
public class ProgramWithNamedListener extends Frame {
private class InnerWindowCloser extends WindowAdapter{
public void windowClosing(WindowEvent we){
	System.exit(0);
}
}
public ProgramWithNamedListener()
{
	InnerWindowCloser x=new InnerWindowCloser();
	addWindowListener(x);
	setSize(200,200);
	setVisible(true);
	}
public static void main(String args[])
{
	ProgramWithNamedListener p=new ProgramWithNamedListener();
}
}

在这里插入图片描述

(6)典型的事件、构件、监听接口之间的关系

1)ActionEvent事件

触发时机:单击按扭,双击列表框中选项,选择菜单项,文本框中按回车键
事件监听接口:ActionListener
接口方法:actionPerformed(ActionEvent e)
组件注册该事件方法:addActionListener(监听者)

2) AdjustmentEvent事件

触发时机:操作滚动条改变滑块位置
事件监听接口:AdjustmentListener
接口方法:adjustmentValueChanged(AdjustmentEvent e)
组件注册该事件方法:addAdjustmentListener(监听者)

3) ComponentEvent 事件

触发时机:当组件移动、改变大小、改变可见性时引发
事件监听接口:ComponentListener
接口方法:
组件隐藏:componentHidden(ComponentEvent e)
组件移动:componentMoved(ComponentEvent e)
组件改变大小:componentResized(ComponentEvent e)
组件变为可见:componentShown(ComponentEvent e)
接口适配器 :ComponentAdapter
组件注册该事件方法:addComponentListener

4) ContainerEvent 事件

触发时机:当容器增加或删除组件时引发
事件监听接口:ContainerListener
接口方法:
容器内加入组件:componentAdded(ContainerEvent e)
从容器中移走组件:componentRemoved(ContainerEvent e)
接口适配器 :ContainerAdapter
容器注册该事件方法:addContainerListener

5) FocusEvent事件

触发时机:组件获得焦点、组件失去焦点
事件监听接口: FocusListener
接口方法:
组件获得焦点时调用:focusGained(FocusEvent e)
组件失去焦点时调用:focusLost(FocusEvent e)
接口适配器:FocusAdapter
组件注册该事件方法:addFocusListener (监听者)

6) ItemEvent事件

触发时机:改变列表框中的选中项、改变复选框选中状态、改变下拉列表框的选中项
事件监听接口:ItemListener
接口方法:itemStateChanged(ItemEvent e)
组件注册该事件方法:addItemListener(监听者)

7) TextEvent事件

触发时机:输入字符到文本框或文本区域
事件监听接口:TextListener
接口方法:textValueChanged(TextEvent e)
组件注册该事件方法:addTextListener(监听者)

8) KeyEvent事件

KeyEvent的方法:
返回键盘输入的字符:char getKeyChar()
返回键盘码:int getKeyCode()
事件监听适配器(抽象类):KeyAdapter
组件注册该事件方法:addKeyListener(监听者)

9) WindowEvent事件

触发时机:有关窗口操作引发的事件
事件监听:WindowListener
接口方法:
windowActivated(WindowEvent e) 激活窗口
windowClosed(WindowEvent e) 调用dispose方法关闭窗口
windowClosing(WindowEvent e) 调用窗口关闭框关闭窗口
windowDeactivated(WindowEvent e) 本窗口成为非活动窗口

10) MouseEvent事件

触发时机:(鼠标作用在一个组件上)
鼠标事件:鼠标键按下,鼠标键抬起,单击鼠标 ,鼠标光标进入一个组件,鼠标光标离开一个组件。
鼠标移动事件:鼠标移动,鼠标拖动
鼠标事件监听接口1:
MouseListener 接受鼠标事件

  • 18
    点赞
  • 142
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长街395

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值