资源描述
Java图形用户界面 Java界面设计的用途n Java 的图形界面工具包,可以用于工具类软件开发、管理类软件开发、通用客户端开发、银行客户端软件开发、Eclipse 插件开发等方向。在许多知名的大型软件中,都能够见到 Java 的身影,如思维导图软件、Eclipse、IDEA 开发环境等。 2 AWT简介n Abstract Windows Toolkit(AWT)是最原始的 Java GUI 工具包。它是一个非常简单的具有有限 GUI 组件、布局管理器和事件的工具包(如窗体、文本标签、按钮、菜单等)。 3 Swing简介n Swing 是 Sun 开发的一个经过仔细设计的、灵活而强大的 GUI 工具包。Swing 是在 AWT 组件基础上构建的。Swing 使用了 AWT 的事件模型和支持类,例如 Colors、Images 和 Graphics。Swing 组件、布局管理器以及事件比 AWT 提供的组件集更为广泛,完全满足各种开发需求。 4 SWT简介n SWT 也是基于一个对等体实现的,在这一点上它与 AWT 非常类似。基于 SWT 的 GUI 既具有主机外观,又具有主机的性能。这样就避免了使用 AWT 和 Swing 而引起的大部分问题。nSWT是IBM为它的Eclipse集成开发环境而开发的图形用户界面工具。SWT可以在Eclipse环境外使用,而且提供对操作系统本地图形用户界面的直接访问。因此,基于SWT的Java应用程序拥有本地的图形用户界面并且可以和本地别的应用程序和部件集成在一起。 5 如何选择 GUI 工具包n AWT、Swing、SWT是 Java 中的三大 GUI 工具包,其中 Swing 是最灵活、强大的 GUI 工具包,所以在界面开发中,首选 Swing ,它可以胜任绝大多数开发工作。 6 7 本讲内容n 1、AWT事件处理模型n 2、布局管理器n 3、Swing简介n 4、Swing组件和容器 8 用AWT生成图形化用户界面 抽象窗口工具包AWT (Abstract Window Toolkit) 是 API为Java 程序提供的建立图形用户界面GUI (Graphics User Interface)工具集,AWT可用于Java的applet和applications中。它支持图形用户界面编程的功能包括: 用户界面组件;事件处理模型;图形和图像工具,包括形状、颜色和字体类;布局管理器,可以进行灵活的窗口布局而与特定窗口的尺寸和屏幕分辨率无关;数据传送类,可以通过本地平台的剪贴板来进行剪切和粘贴。 9 1 用AWT生成图形化用户界面n java.awt包中包含了一个完整的类集以支持GUI程序的设计(重量级构件)事件类字体类GraphicsComponent颜色类布局管理类java.lang.ObjectCheckbox ContainerButton Window Panel AppletDialogFrameList图象类菜单类 10 1.1 java.awt包 n java.awt包中提供了GUI设计所使用的类和接口。 n java.awt包提供了基本的java程序的GUI设计工具。主要包括下述三个概念:组件Component容器Container 布局管理器-LayoutManager 11 1.2 组件和容器 n Java的图形用户界面的最基本组成部分是组件(Component),组件是一个可以以图形化的方式显示在屏幕上并能与用户进行交互的对象,例如一个按钮,一个标签等。组件不能独立地显示出来,必须将组件放在一定的容器中才可以显示出来。 n类java.awt.Component是许多组件类的父类,Component类中封装了组件通用的方法和属性,如图形的组件对象、大小、显示位置、前景色和背景色、边界、可见性等,因此许多组件类也就继承了Component类的成员方法和成员变量,相应的成员方法包括:getComponentAt(int x, int y) getFont()getForeground() getName() getSize() paint(Graphics g)repaint() update()setVisible(boolean b) setSize(Dimension d)setName(String name)等 12 1.2 组件和容器n容器(Container)也是一个类,实际上是Component的子类,因此容器本身也是一个组件,具有组件的所有性质,但是它的主要功能是容纳其它组件和容器。n布局管理器(LayoutManager):每个容器都有一个布局管理器,当容器需要对某个组件进行定位或判断其大小尺寸时,就会调用其对应的布局管理器。 n为了使我们生成的图形用户界面具有良好的平台无关性,Java语言中,提供了布局管理器这个工具来管理组件在容器中的布局,而不使用直接设置组件位置和大小的方式。 13 1.2 组件和容器n在程序中安排组件的位置和大小时,应该注意以下两点: 1容器中的布局管理器负责各个组件的大小和位置,因此用户无法在这种情况下设置组件的这些属性。如果试图使用Java 语言提供的setLocation(),setSize(),setBounds() 等方法,则都会被布局管理器覆盖。 2如果用户确实需要亲自设置组件大小或位置,则应取消该容器的布局管理器,方法为:setLayout(null); 14 1.3 常用容器 n容器java.awt.Container是Component的子类,一个容器可以容纳多个组件,并使它们成为一个整体。容器可以简化图形化界面的设计,以整体结构来布置界面。所有的容器都可以通过add()方法向容器中添加组件。有三种类型的容器:Window、Panel、ScrollPane,常用的有Panel, Frame, Applet。 15 1.3 常用容器-Framen 1Frame例: import java.awt.*;public class MyFrame extends Framepublic static void main(String args )MyFrame fr = new MyFrame(Hello Out There!); /构造方法fr.setSize(200,200); /设置Frame的大小,缺省为(0,0)fr.setBackground(Color.red);/设置Frame的背景,缺省为红色fr.setVisible(true); /设置Frame为可见,缺省为不可见public MyFrame (String str)super(str); /调用父类的构造方法 16 1.3 常用容器-Framen一般我们要生成一个窗口,通常是用Window的子类Frame来进行实例化,而不是直接用到Window类。Frame的外观就像我们平常在windows系统下见到的窗口,有标题、边框、菜单、大小等等。每个Frame的对象实例化以后,都是没有大小和不可见的,因此必须调用setSize( )来设置大小,调用setVisible(true)来设置该窗口为可见的。 n另外,AWT在实际的运行过程中是调用所在平台的图形系统,因此同样一段AWT程序在不同的操作系统平台下运行所看到的图形系统是不一样的。例如在windows下运行,则显示的窗口是windows风格的窗口;而在UNIX下运行时,则显示的是UNIX风格的窗口。 17 1.3 常用容器n 2Panel n Panel与Frame类似,可以添加到Frame中。 18 1.4 LayoutManager 布局管理器n Java为了实现跨平台的特性并且获得动态的布局效果,Java将容器内的所有组件安排给一个布局管理器负责管理,如:排列顺序,组件的大小、位置,当窗口移动或调整大小后组件如何变化等功能授权给对应的容器布局管理器来管理,不同的布局管理器使用不同算法和策略,容器可以通过选择不同的布局管理器来决定布局。 n布局管理器主要包括:FlowLayout,BorderLayout,GridLayout,CardLayout,GridBagLayout: 19 1.4 布局管理器-FlowLayoutn 1. FlowLayoutFlowLayout 是Panel,Applet的缺省布局管理器。其组件的放置规律是从上到下、从左到右进行放置,如果容器足够宽,第一个组件先添加到容器中第一行的最左边,后续的组件依次添加到上一个组件的右边,如果当前行已放置不下该组件,则放置到下一行的最左边。 当容器的大小发生变化时,用FlowLayout管理的组件会发生变化,其变化规律是:组件的大小不变,但是相对位置会发生变化。例如上图中有三个按钮都处于同一行,但是如果把该窗口变窄,窄到刚好能够放下一个按钮,则第二个按钮将折到第二行,第三个按钮将折到第三行。按钮Open本来在按钮OK的右边,但是现在跑到了下面,所以说组件的大小不变,但是相对位置会发生变化。 20 1.4 布局管理器-FlowLayoutn构造方法主要下面几种: FlowLayout(FlowLayout.RIGHT,20,40);/*第一个参数表示组件的对齐方式,指组件在这一行中的位置是居中对齐、居右对齐还是居左对齐,第二个参数是组件之间的横向间隔,第三个参数是组件之间的纵向间隔,单位是象素。*/ FlowLayout(FlowLayout.LEFT); /居左对齐,横向间隔和纵向间隔都是缺省值5个象素 FlowLayout(); /缺省的对齐方式居中对齐,横向间隔和纵向间隔都是缺省值5个象素 n例:Frame f = new Frame(); f.setLayout(new FlowLayout();f.add(new Button(button1);f.add(new Button( button2);f.add(new Button( button3); 21 1.4 布局管理器-BorderLayout n BorderLayout 是Window,Frame和Dialog的缺省布局管理器。BorderLayout布局管理器把容器分成5个区域:North,South,East,West和Center,每个区域只能放置一个组件。f.setLayout(new BorderLayout();f.add(North, new Button(North);/第一个参数表示把按钮添加到容器的North区域 n在使用BorderLayout的时候,如果容器的大小发生变化,其变化规律为:组件的相对位置不变,大小发生变化。例如容器变高了,则North、South区域不变,West、Center、East区域变高;如果容器变宽了,West、East区域不变,North、Center、South区域变宽。不一定所有的区域都有组件,如果四周的区域(West、East、North、South区域)没有组件,则由Center区域去补充,但是如果Center区域没有组件,则保持空白:CenterNorthSouthWest East 22 1.4 布局管理器-GridLayoutn使容器中各个组件呈网格状布局,平均占据容器的空间。 n Frame f = new Frame(GridLayout);f.setLayout(new GridLayout(3,2); /容器平均分成3行2列共6格f.add(new Button(1); /添加到第一行的第一格f.add(new Button(2); /添加到第一行的下一格.f.add(new Button(6); /添加到第二行的第三格 23 1.4 布局管理器-CardLayoutCardLayout布局管理器能够帮助用户处理两个以至更多的成员共享同一显示空间,它把容器分成许多层,每层的显示空间占据整个容器的大小,但是每层只允许放置一个组件,当然每层都可以利用Panel来实现复杂的用户界面。牌布局管理器(CardLayout)就象一副叠得整整齐齐的扑克牌一样,有54张牌,但是你只能看见最上面的一张牌,每一张牌就相当于牌布局管理器中的每一层。 24 1.4 布局管理器n容器的嵌套在复杂的图形用户界面设计中,为了使布局更加易于管理,具有简洁的整体风格,一个包含了多个组件的容器本身也可以作为一个组件加到另一个容器中去,容器中再添加容器,这样就形成了容器的嵌套。下面是一个容器嵌套的例子。n例:f = new Frame(GUI example 3);bw=new Button(West);bc=new Button(Work space region);f.add(bw,West);f.add(bc,Center);p = new Panel();f.add(p,North);bfile= new Button(File); bhelp= new Button(Help);p.add(bfile); p.add(bhelp);f.pack(); f.setVisible(true); 25 1.4 布局管理器小 结:1Frame是一个顶级窗口。Frame的缺省布局管理器为BorderLayout。2Panel 无法单独显示,必须添加到某个容器中。 Panel 的缺省布局管理器为FlowLayout。3当把Panel 作为一个组件添加到某个容器中后,该Panel 仍然可以有自己的布局管理器。因此,可以利用Panel 使得BorderLayout 中某个区域显示多个组件,达到设计复杂用户界面的目的 。4如果采用无布局管理器 setLayout(null),则必须使用setLocation(),setSize(),setBounds()等方法手工设置组件的大小和位置,此方法会导致平台相关,不鼓励使用。 26 2 AWT事件处理模型 要能够让图形界面接收用户的操作,就必须给各个组件加上事件处理机制。在事件处理的过程中,主要涉及三类对象: Event-事件,用户对界面操作在java语言上的描述,以类的形式出现,例如键盘操作对应的事件类是KeyEvent。 Event Source-事件源,事件发生的场所,通常就是各个组件,例如按钮Button。 Event handler-事件处理者,接收事件对象并对其进行处理的对象。 27 事件及处理机制n组件(事件发生者)触发一个相应类型的事 件n此事件由相应类型的Listener(事件监听者) 接收并处理Button1事件发生者接收事件e,并做处理ActionListener事件监听者触发ActionEvente点击 28 事件及处理机制 调用按扭的 addActionListener ( ) 方法,为该按扭指定监听者。鼠标单击按扭ActionEvent事件触发public void actionPerformed(ActionEvent e)ActionListener接口ActionEvent事件监听者类监听者对象实现接口 29 实现步骤n根据需要定义相应类型的监听者类,在类的 定义中完成事件的处理;n创建事件监听者对象;n为将会触发事件的组件C注册相应的事件监听 者对象(使用C的addXXXListener()方法)。n例:ButtonAct.java 30 publicclassButtonActextendsFrame.publicButtonAct()./为b1注册事件监听者B1b1.addActionListener(newB1();add(b1);./利用innerclass结构定义监听者类classB1implementsActionListener/利用actionPerformed方法进行事件处理publicvoidactionPerformed(ActionEvente)who.setText(Button1);./: 31 2.1 事件类n与AWT有关的所有事件类都由java.awt.AWTEvent类派生,它也是EventObject类的子类。AWT事件共有10类,可以归为两大类:低级事件和高级事件。n java.util.EventObject类是所有事件对象的基础父类,所有事件都是由它派生出来的。AWT的相关事件继承于java.awt.AWTEvent类,这些AWT事件分为两大类:低级事件和高级事件,低级事件是指基于组件和容器的事件,当一个组件上发生事件,如:鼠标的进入,点击,拖放等,或组件的窗口开关等,触发了组件事件。高级事件是基于语义的事件,它可以不和特定的动作相关联,而依赖于触发此事件的类,如在TextField中按Enter键会触发ActionEvent事件,滑动滚动条会触发AdjustmentEvent事件,或是选中项目列表的某一条就会触发ItemEvent事件。 32 2.1 事件类 低级事件ComponentEvent( 组件事件:组件尺寸的变化,移动) ContainerEvent( 容器事件:组件增加,移动) WindowEvent( 窗口事件:关闭窗口,窗口闭合,图标化) FocusEvent( 焦点事件:焦点的获得和丢失) KeyEvent( 键盘事件:键按下、释放) MouseEvent( 鼠标事件:鼠标单击,移动) 高级事件(语义事件)ActionEvent(动作事件:按钮按下,TextField中按Enter键)AdjustmentEvent(调节事件:在滚动条上移动滑块以调节数值)ItemEvent(项目事件:选择项目,不选择项目改变)TextEvent(文本事件,文本对象改变) 33 2.2 事件监听器n每类事件都有对应的事件监听器,监听器是接口,根据动作来定义方法。 n AWT的组件类中提供注册和注销监听器的方法: 注册监听器:public void add (listener); 注销监听器:public void remove (listener); 例如Button类:(查API)public class Button extends Component public synchronized void addActionListener(ActionListener l); public synchronized void removeActionListener(ActionListener l); 34 2.3 AWT事件及其相应的监听器接口 n 1可以声明多个接口,接口之间用逗号隔开。implements MouseMotionListener, MouseListener, WindowListener; n 2可以由同一个对象监听一个事件源上发生的多种事件:f.addMouseMotionListener(this);f.addMouseListener(this);f.addWindowListener(this);则对象f 上发生的多个事件都将被同一个监听器接收和处理。 35 2.3 AWT事件及其相应的监听器接口n 3事件处理者和事件源处在同一个类中。本例中事件源是Frame f,事件处理者是类ThreeListener,其中事件源Frame f是类ThreeListener的成员变量。在这里所有的事件侦听器方法都要在主类中声明。 public class ThreeListener implements MouseMotionListener,MouseListener,WindowListener f = new Frame(Three listeners example); f.addMouseMotionListener(this); /注册监听器MouseMotionListenerf.addMouseListener(this); /注册监听器MouseListenerf.addWindowListener(this); /注册监听器WindowListener 36 2.3 AWT事件及其相应的监听器接口n 4可以通过事件对象获得详细资料,比如本例中就通过事件对象获得了鼠标发生时的坐标值。public void mouseDragged(MouseEvent e) String s=Mouse dragging :X=+e.getX()+Y=+e.getY();tf.setText(s); n Java语言类的层次非常分明,因而只支持单继承,为了实现多重继承的能力,Java用接口来实现,一个类可以实现多个接口,这种机制比多重继承具有更简单、灵活、更强的功能。在AWT中就经常用到声明和实现多个接口。记住无论实现了几个接口,接口中已定义的方法必须一一实现,如果对某事件不感兴趣,可以不具体实现其方法,而用空的方法体来代替。但却必须所有方法都要写上。 37 2.4 事件适配器n Java语言为一些Listener接口提供了适配器(Adapter)类。可以通过继承事件所对应的Adapter类,重写需要方法,无关方法不用实现。事件适配器为我们提供了一种简单的实现监听器的手段, 可以缩短程序代码。但是,由于java的单一继承机制,当需要多种监听器或此类已有父类时,就无法采用事件适配器了。 38 2.4 事件适配器n 1事件适配器-EventAdapter下例中采用了鼠标适配器:import java.awt.*;import java.awt.event.*;public class MouseClickHandler extends MouseAdaperpublic void mouseClicked(MouseEvent e) /只实现需要的方法 n java.awt.event包中定义的事件适配器类包括以下几个:1ComponentAdapter( 组件适配器) 2ContainerAdapter( 容器适配器) 3FocusAdapter( 焦点适配器) 4KeyAdapter( 键盘适配器) 5MouseAdapter( 鼠标适配器) 6MouseMotionAdapter( 鼠标运动适配器)7WindowAdapter( 窗口适配器) 39 2.4 事件适配器n 2. 用内部类实现事件处理内部类(inner class)是被定义于另一个类中的类,使用内部类的主要原因是由于: 一个内部类的对象可访问外部类的成员方法和变量,包括私有的成员。 实现事件监听器时,采用内部类、匿名类编程非常容易实现其功能。 编写事件驱动程序,内部类很方便。 注意:使用的内部类不能在静态方法(如main方法)中调用。 40 import java.awt.* ;import java.awt.event.*;public class InnerClassprivate Frame f;private TextField tf;public InnerClass()f=new Frame(Inner classes example);tf=new TextField(30);public voidi launchFrame()Label label=new Label(Click and drag the mouse);f.add(label,BorderLayout.NORTH);f.add(tf,BorderLayout.SOUTH);f.addMouseMotionListener(new MyMouseMotionListener();/*参数为内部类对象*/f.setSize(300,200);f.setVisible(true); class MyMouseMotionListener extends MouseMotionAdapter /*内部类开始*/public void mouseDragged(MouseEvent e) String s=Mouse dragging: x=+e.getX()+Y=+e.getY();tf.setText(s); ; public static void main(String args) InnerClass obj=new InnerClass();obj.launchFrame();/内部类结束 41 2.4 事件适配器n 3匿名类(Anonymous Class)当一个内部类的类声名只是在创建此类对象时用了一次,而且要产生的新类需继承于一个已有的父类或实现一个接口,才能考虑用匿名类,由于匿名类本身无名,因此它也就不存在构造方法,它需要显示地调用一个无参的父类的构造方法,并且重写父类的方法。所谓的匿名就是该类连名字都没有,只是显示地调用一个无参的父类的构造方法。 n f.addMouseMotionListener(new MouseMotionAdapter() /匿名类开始public void mouseDragged(MouseEvent e)String s=Mouse dragging: x=+e.getX()+Y=+e.getY();tf.setText(s); ); /匿名类结束 42 3 AWT组件库 n本节从应用的角度进一步介绍AWT的一些组件,目的使大家加深对AWT的理解,掌握如何用各种组件构造图形化用户界面,学会控制组件的颜色和字体。下面是一些常用的组件的介绍: 43 3 AWT组件库n 1 按钮(Button)按钮是最常用的一个组件,其构造方法是:Button b = new Button(Quit); 当按钮被点击后,会产生ActionEvent事件,需ActionListener接口进行监听和处理事件。ActionEvent的对象调用getActionCommand()方法可以得到按钮的标识名,缺省按钮名为label。用setActionCommand()可以为按钮设置组件标识符。 44 3 AWT组件库n 2.复选框 (Checkbox)复选框提供简单的on/off开关,旁边显示文本标签。构造方法如下:setLayout(new GridLayout(3,1);add(new Checkbox(one,null,true);add(new Checkbox(two);add(new Checkbox(three);复选框用ItemListener 来监听ItemEvent事件,当复选框状态改变时用getStateChange()获取当前状态。使用getItem()获得被修改复选框的字符串对象。 n class Handler implements ItemListener public void itemStateChanged(ItemEvent ev)String state = deselected;if (ev.getStateChange() = = ItemEvent.SELECTED)state = selected System.out.println(ev.getItem()+ +state); 45 3 AWT组件库n 3.复选框组(CheckboxGroup)使用复选框组,可以实现单选框的功能。方法如下: setLayout(new GridLayout(3, 1);CheckboxGroup cbg = new CheckboxGroup();add(new Checkbox(one, cbg, true);add(new Checkbox(two, cbg, false);add(new Checkbox(three, cbg, false); 46 3 AWT组件库n 4. 下拉式菜单(Choice)下拉式菜单每次只能选择其中的一项,它能够节省显示空间,适用于大量选项。Choice Colorchooser=new Choice();Colorchooser.add(Green);Colorchooser.add(Red);Colorchooser.add(Blue);Choice 用ItemListener接口来进行监听 47 3 AWT组件库n 5. Canvas一个应用程序必须继承Canvas类才能获得有用的功能,比如创建一个自定义组件。如果想在画布上完成一些图形处理,则Canvas类中的paint()方法必须被重写。Canvas组件监听各种鼠标,键盘事件。当在Canvas组件中输入字符时,必须先调用requestFocus()方法。 48 3 AWT组件库n 6. 单行文本输入区(TextField)只能显示一行,当回车键被按下时,会发生ActionEvent事件,可以通过ActionListener中的actionPerformed()方法对事件进行相应处理。可以使用setEditable(boolean)方法设置为只读属性。单行文本输入区构造方法如下:TextField tf1,tf2,tf3,tf4:tf1=new TextField(); tf2=new TextField(,20); /显示区域为20列tf3=new TextField(Hello!); /按文本区域大小显示tf4=new TextField(Hello!,30); /初始文本为Hello!, 显示区域为30列 49 3 AWT组件库n 7. 文本输入区(TextArea)TextArea可以显示多行多列的文本。使用setEditable(boolean)方法,可以将其设置为只读的。在TextArea中可以显示水平或垂直的滚动条。要判断文本是否输入完毕,可以在TextArea旁边设置一个按钮,通过按钮点击产生的ActionEvent对输入的文本进行处理。 n 8. 列表(List)列表中提供了多个文本选项,列表支持滚动条,可以浏览多项List lst=new List(4,false); /两个参数分别表示显示的行数、是否允许多选lst.add(Venus);lst.add(Earth);lst.add(JavaSoft); lst.add(Mars);cnt.add(lst); 50 3 AWT组件库n 9. 框架(Frame)Frame是顶级窗口,可以显示标题,重置大小。当Frame被关闭,将产生WindowEvent事件,Frame无法直接监听键盘输入事件。 n 10. 对话框(Dialog)它是Window类的子类。对话框和一般窗口的区别在于它依赖于其它窗口。对话框分为非模式(non-modal)和模式(modal)两种。n 11. 文件对话框(Filedialog)当用户想打开或存储文件时,使用文件对话框进行操作。主要代码如下: FileDialog d=new FileDialog(ParentFr,FileDialog);d.setVisible(true);String filename=d.getFile(); 51 3 AWT组件库n 12. 菜单(Menu)无法直接将菜单添加到容器的某一位置,也无法使用布局管理器对其加以控制。菜单只能被添加?quot;菜单容器(MenuBar)中。 n 13. MenuBar只能被添加到Frame对象中,作为整个菜单树的根基。Frame fr = new Frame(MenuBar);MenuBar mb = new MenuBar();fr.setMenuBar(mb);fr.setSize(150,100);fr.setVisible(true); 52 3 AWT组件库n 14. Menu下拉菜单。它可以被添加到MenuBar中或其它Menu中。Frame fr = new Frame(MenuBar);MenuBar mb = new MenuBar();fr.setMenuBar(mb);Menu m1 = new Menu(File);mb.add(m1);n 15. MenuItemMenuItem是菜单树中的叶子节点。MenuItem通常被添加到一个Menu中。对于MenuItem对象可以添加ActionListener,使其能够完成相应的操作。Menu m1 = new Menu(File);MenuItem mi1 = new MenuItem(Save); 53 本讲小结-AWT用AWT来生成图形化用户界面时,组件和容器的概念非常重要。组件是各种各样的类,封装了图形系统的许多最小单位,例如按钮、窗口等等;而容器也是组件,它的最主要的作用是装载其它组件,但是象Panel这样的容器也经常被当作组件添加到其它容器中,以便完成杂的界面设计。布局管理器是java语言与其它编程语言在图形系统方面较为显著的区别,容器中各个组件的位置是由布局管理器来决定的,共有5种布局管理器,每种布局管理器都有自己的放置规律。事件处理机制能够让图形界面响应用户的操作,主要涉及到事件源、事件、事件处理者等三方,事件源就是图形界面上的组件,事件就是对用户操作的描述,而事件处理者是处理事件的类。因此,对于AWT中所提供的各个组件,我们都需要了解该组件经常发生的事件以及处理该事件的相应的监听器接口。 54 4 Swing简介 55 4.1 简介前面我们学习了AWT,AWT是Swing的基础。Swing的产生主要原因就是AWT不能满足图形化用户界面发展的需要。AWT设计的初衷是支持开发小应用程序的简单用户界面。例如AWT缺少剪贴板、打印支持、键盘导航等特性,而且原来的AWT甚至不包括弹出式菜单或滚动窗格等基本元素。此外AWT还存在着严重的缺陷,人们使AWT适应基于继承的、具有很大伸缩性的事件模型,基于同位体的体系结构也成为其致命的弱点。随着发展的需要,Swing出现了,Swing组件几乎都是轻量组件,与重量组件相比,没有本地的对等组件,不像重量组件要在它们自己的本地不透明窗体中绘制,轻量组件在它们的重量组件的窗口中绘制。 56 4.1 简介n Swing是由100%纯Java实现的,Swing组件是用Java实现的轻量级( light-weight)组件,没有本地代码,不依赖操作系统的支持,这是它与AWT组件的最大区别。由于AWT组件通过与具体平台相关的对等类(Peer)实现,因此Swing比AWT组件具有更强的实用性。Swing在不同的平台上表现一致,并且有能力提供本地窗口系统不支持的其它特性。 n Swing采用了一种MVC的设计范式,即模型-视图-控制(Model-View-Controller),其中模型用来保存内容,视图用来显示内容,控制器用来控制用户输入。 n在AWT组件中,由于控制组件外观的对等类与具体平台相关,使得AWT组件总是只有与本机相关的外观。Swing使得程序在一个平台上运行时能够有不同的外观。用户可以选择自己习惯的外观。 57 4.2 Swing的类层次结构 n在javax.swing包中,定义了两种类型的组件:顶层容器(JFrame,JApplet,JDialog和JWindow)和轻量级组件。Swing组件都是AWT的Container类的直接子类和间接子类。n java.awt.Component-java.awt.Container-java.awt.Window-java.awt.Frame-javax.swing.JFrame-javax.Dialog-javax.swing.JDialog-javax.swing.JWindow-java.awt.Applet-javax.swing.JApplet -javax.swing.Box-javax.swing.Jcomponet 58 4.2 Swing的类层次结构swing包是Swing提供的最大包,它包含将近100个类和25个接口,几乎所有的Swing组件都在swing包中,只有JtableHeader和JtextComponent是例外,它们分别在swing.table和swing.text中。swing.border包中定义了事件和事件监听器类,与AWT的event包类似。它们都包括事件类和监听器接口。swing.pending包包含了没有完全实现的Swing组件。swing.table包中主要包括了表格组建(JTable)的支持类。swing.tree同样是JTree的支持类。swing.text、swing.text.html、swing.text.html.parser和swing.text.rtf都是用于显示和编辑文档的包。 59 4.3 Swing组件的多样化 n Swing是AWT的扩展,它提供了许多新的图形界面组件。Swing组件以J开头,除了有与AWT类似的按钮(JButton)、标签(JLabel)、复选框(JCheckBox)、菜单(JMenu)等基本组件外,还增加了一个丰富的高层组件集合,如表格(JTable)、树(JTree)。 60 4.4 MVC(Model-View-Control)体系结构Swing胜过AWT的主要优势在于MVC体系结构的普遍使用。在一个MVC用户界面中,存三个通讯对象:模型、视图和控件。模型是指定的逻辑表示法,视图是模型的可视化表示法,而控件则指定了如何处理用户输入。当模型发生改变时,它会通知所有依赖它的视图,视图使用控件指定其相应机制。 为了简化组件的设计工作,在Swing组件中视图和控件两部分合为一体。每个组件有一个相关的分离模型和它使用的界面(包括视图和控件)。比如,按钮JButton有一个存储其状态的分离模型ButtonModel对象。组件的模型是自动设置的,例如一般都使用JButton 而不是使用ButtonModel 对象。另外,通过Model类的子类或通过实现适当的接口,可以为组件建立自己的模型。把数据模型与组件联系起来用setModel( )方法。MVC是现有的编程语言中制作图形用户界面的一种通用的思想,其思路是把数据的内容本身和显示方式分离开,这样就使得数据的显示更加灵活多样。比如,某年级 各个班级的学生人数是数据,则显示方式是多种多样的,可以采用柱状图显示,也可以采用饼图显示,也可以采用直接的数据输出。因此在设计的时候,就考虑把数据和显示方式分开,对于实现多种多样的显示是非常有帮助的。 61 4.5 可存取性支持 n所有Swing组件都实现了Accessible接口,提供对可存取性的支持,使得辅助功能如屏幕阅读器能够十分方便的从Swing组件中得到信息。 62 4.6 支持键盘操作 n在Swing组件中,使用JComponent类的registerKeyboardAction()方法,能使用户通过键盘操作来替代鼠标驱动GUI上Swing组件的相应动作。有些类还为键盘操作提供了更便利的方法。即设定热键。 63 4.7 设置边框 n对Swing组件可以设置一个和多个边框。Swing中提供了各式各样的边框供用户选用,也能建立组合边框或自己设计边框。一种空白边框可以增大组件,协助布局管理器对容器中的组件进行合理的布局。 64 4.8 使用图标(Icon) n与AWT的部件不同,许多Swing组件如按钮、标签,除了使用文字外,还可以使用图标修饰自己。 65 4.9 Swing程序结构简介 n Swing的程序设计一般可按照下列流程进行:1 引入Swing包2 选择外观和感觉3 设置顶层容器4 设置按钮和标签5 向容器中添加组件6 在组件周围添加边界7 进行事件处理 66 5 Swing组件和容器 67 5.1 组件的分类 n Jcomponent是一个抽象类,用于定义所有子类组件的一般方法,其类层次结构如下所示: java.lang.Object|+-java.awt.Component|+-java.awt.Container|+-javax.swing.JComponent并不是所有的Swing组件都继承于JComponent类,JComponent类继承于Container类,所以凡是此类的组件都可作为容器使用。 68 5.1 组件的分类n组件从功能上分可分为:1) 顶层容器:JFrame,JApplet,JDialog,JWindow共4个2) 中间容器:JPanel,JScrollPane,JSplitPane,JToolBar3) 特殊容器:在GUI上起特殊作用的中间层,如JInternalFrame,JLayeredPane,JRootPane.4) 基本控件:实现人际交互的组件,如Jbutton, JComboBox, JList, JMenu, JSlider, JtextField。5) 不可编辑信息的显示:向用户显示不可编辑信息的组件,例如JLabel, JProgressBar, ToolTip。6) 可编辑信息的显示:向用户显示能被编辑的格式化信息的组件,如JColorChooser, JFileChoose, JFileChooser, Jtable, JtextArea。 69 5.1 组件的分类n JComponent类的特殊功能又分为:1) 边框设置:使用setBorder()方法可以设置组件外围的边框,使用一个EmptyBorder对象能在组件周围留出空白。 2) 双缓冲区:使用双缓冲技术能改进频繁变化的组件的显示效果。与AWT组件不同,JComponent组件默认双缓冲区,不必自己重写代码。如果想关闭双缓冲区,可以在组件上施加setDoubleBuffered(false)方法。3) 提示信息:使用setTooltipText()方法,为组件设置对用户有帮助的提示信息。4) 键盘导航:使用registerKeyboardAction( ) 方法,能使用户用键盘代替鼠标来驱动组件。JComponent类的子类AbstractButton还提供了便利的方法用setMnemonic( )方法指明一个字符,通过这个字符和一个当前L/把其它组件添加到Jpanel中; frame.setContentPane(contentPane); /把contentPane对象设置成为frame的内容面板 71 5.3 各种容器面板和组件 72 5.3.1 根面板(JRootPane)n根面板由一个玻璃面板(glassPane)、一个内容面板(contentPane)和一个可选择的菜单条(JMenuBar)组成,而内容面板和可选择的菜单条放在同一分层。玻璃面板是完全透明的,缺省值为不可见,为接收鼠标事件和在所有组件上绘图提供方便。根面板提供的方法:Container getContentPane(); /获得内容面板setContentPane(Container); /设置内容面JMenuBar getMenuBar( ); /活动菜单条setMenuBar(JMenuBar); /设置菜单条JLayeredPane getLayeredPane(); /获得分层面板setLayeredPane(JLayeredPane); /设置分层面板Component getGlassPane(); /获得玻璃面板setGlassPane(Component); /设置玻璃面板 73 5.3.2 分层面板(JLayeredPane) n Swing提供两种分层面板:JlayeredPane和JDesktopPane。 JDesktopPane是JLayeredPane的子类,专门为容纳内部框架(JInternalFrame)而设置。向一个分层面板种添加组件,需要说明将其加入哪一层,指明组件在该层中的位置:add(Component c, Integer Layer, int position)。 74 5.3.3 面板(JPanel) n面板(JPanel)是一个轻量容器组件,用法与Panel相同,用于容纳界面元素,以便在布局管理器的设置下可容纳更多的组件,实现容器的嵌套。Jpanel, JscrollPane, JsplitPane, JinteralFrame都属于常用的中间容器,是轻量组件。Jpanel的缺省布局管理器是FlowLayout。 75 5.3.4 滚动窗口(JScrollPane) n JscrollPane是带滚动条的面板,主要是通过移动JViewport(视口)来实现的。JViewport是一种特殊的对象,用于查看基层组件,滚动条实际就是沿着组件移动视口,同时描绘出它在下面看到的内容。 76 5.3.5 分隔板(JSplitPane) n JSplitPane提供可拆分窗口,支持水平拆分和垂直拆分并带有滑动条。 常用方法有:addImpl(Component comp,Object constraints,int index)/增加指定的组件setTopComponent(Component comp) /设置顶部的组件setDividerSize(int newSize) /设置拆分的大小setUI(SplitPaneUI ui) /设置外观和感觉 77 5.3.6 选项板(JTabbedPane) n JTabbedPane提供一组可供用户选择的带有标签或图标的开关键。常用方法:add(String title,Component component) /增加一个带特定标签的组件addChangeListener(ChangeListener l) /选项板注册一个变化监听器 78 5.3.7 工具栏(JtoolBar) n JtoolBar是用于显示常用工具控件的容器。用户可以拖拽出一个独立的可显示工具控件的窗口。常用方法有:JToolBar(String name) /构造方法getComponentIndex(Component c) /返回一个组件的序号getComponentAtIndex(int i) /得到一个指定序号的组件 79 5.3.8 内部框架(JInternalFrame) n内部框架JInternalFrame就如同一个窗口在另一个窗口内部,其特点如下:1) 必须把内部框架添加到一个容器中(通常为JDesktopPane),否则不显示;2) 不必调用show()或setVisible()方法,内部框架随所在的容器一起显示;3) 必须用setSize()或pack()或setBounds方法设置框架尺寸,否则尺寸为零,框架不能显示;4) 可以用setLocation()或setBounds( ) 方法设置内部框架在容器中的位置,缺省值为0,0,即容器的左上角;5) 象顶层JFrame一样,对内部框架添加组件也要加在它的内容面板上;6) 在内部框架中建立对话框,不能使用JDialog作为顶层窗口,必须用JOptionPane或JInternalFrame;7) 内部框架不能监听窗口事件,可以通过监听与窗口事件类似的内部框架(JInternalFrameEvent)处理内部框架窗口的操作。 80 5.3.8 内部框架(JInternalFrame)JFrame frame=new JFrame(InternalFrameDemo); /实例化窗口JDesktopPane desktop=new JDesktopPane(); /实例化容器JDesktopPaneMyInternalFrame myframe=new MyInternalFrame(); /实例化内部窗口desktop.add(myframe); /把内部窗口添加到容器中myframe.setSelected(true); /内部面板是可选择的frame.setContentPane(desktop); /把desktop设为frame的内容面板 81 5.3.9 按钮(Jbutton) n按钮是一个常用组件,按钮可以带标签或图象。 n常用的构造方法有:JButton(Icon icon) /按钮上显示图标JButton(String text) /按钮上显示字符JButton(String text, Icon icon) /按钮上既显示图标又显示字符 82 n 5.3.10 复选框(JCheckBox) n 5.3.11 单选框(JRadioButton)n 5.3.12 选择框(JCo
展开阅读全文