java语言学习后续 301页

  • 1.19 MB
  • 2022-08-11 发布

java语言学习后续

  • 301页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档由用户上传,淘文库整理发布,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,请立即联系网站客服。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细阅读内容确认后进行付费下载。
  4. 网站客服QQ:403074932
第7章图形用户界面的设计与实现7.1图形用户界面概述7.2用户自定义成分7.3Java的事件处理7.4GUI标准组件概述7.5标签、按钮与动作事件7.6文本框、文本区域与文本事件7.7单、复选按钮,列表与选择事件\n7.8滚动条与调整事件7.9画布与鼠标、键盘事件7.10布局设计7.11Panel与容器事件7.12Frame与窗口事件7.13菜单的定义与使用7.14对话框、组件事件与焦点事件7.15小结习题\n本章介绍Java程序中图形用户界面(GUI)的设计与实现。图形用户界面是程序与用户交互的窗口。每个图形界面下的Java程序都必须设计、建立自己的图形用户界面并利用它接受用户的输入,向用户输出程序运行的结果。本章将介绍图形用户界面的基本组成和主要操作,包括绘制图形,显示动画,使用AWT包各组件和实现Java的事件处理功能等。\n7.1图形用户界面概述设计和构造用户界面,是软件开发中的一项重要工作。用户界面是计算机的使用者——用户与计算机系统交互的接口,用户界面功能是否完善,使用是否方便,将直接影响到用户对应用软件的使用。图形用户界面(graphicsuserinterface)简称GUI,使用图形的方式借助菜单、按钮等标准界面元素和鼠标操作,帮助用户方便地向计算机系统发出命令,启动操作,并将系统运行的结果同样以图形的方式显示给用户。图形用户界面操作简便,省去了字符界面用户必须记忆各种命令的麻烦,已经成为目前几乎所有应用软件的既成标准。所以,学习设计和开发图形用户界面,是软件开发人员必修的一课。\n随着图形用户界面的普及和界面元素标准化程度的提高,许多辅助设计和实现图形用户界面的方法和工具也相应出现,例如,可视化编程方法允许设计人员直接绘出图形界面,然后交给专门的工具自动编码生成这个图形界面,免除了开发者的许多编程负担,目前许多应用软件开发工具都具有可视化编程的功能。Java语言中,为了方便图形用户界面的开发,设计了专门的类库来生成各种标准图形界面元素和处理图形界面的各种事件。这个用来生成图形用户界面的类库就是java.awt包。AWT是abstractwindowtoolkit(抽象窗口工具集)的缩写。\n所谓抽象,是因为Java是一种跨平台的语言,要求Java程序能在不同的平台系统上运行,这对于图形用户界面尤其困难。为了达到这个目标,AWT类库中的各种操作被定义成在一个并不存在的“抽象窗口”中进行。正如Java虚拟机使得Java程序独立于具体的软硬件平台一样,“抽象窗口”使得开发人员所设计的界面独立于具体的界面实现。也就是说,开发人员用AWT开发出的图形用户界面可以适用于所有的平台系统。当然,这仅是理想情况。实际上AWT的功能还不是很完全,Java程序的图形用户界面在不同的平台上(例如,在不同的浏览器中)可能会出现不同的运行效果,如窗口大小、字体效果将发生变化等。\n首先考察一下图形用户界面的构成。简单地说,图形用户界面就是一组图形界面成分和界面元素的有机组合,这些成分和元素之间不但外观上有着包含、相邻、相交等物理关系,内在的也有包含、调用等逻辑关系,它们互相作用、传递消息,共同组成一个能响应特定事件、具有一定功能的图形界面系统。\n设计和实现图形用户界面的工作主要有两个:①创建组成界面的各成分和元素,指定它们的属性和位置关系,根据具体需要排列它们,从而构成完整的图形用户界面的物理外观。②定义图形用户界面的事件和各界面元素对不同事件的响应,从而实现图形用户界面与用户的交互功能。Java中构成图形用户界面的各种元素和成分可以粗略地被分为三类:容器、控制组件和用户自定义成分。\n1.容器容器是用来组织其他界面成分和元素的单元。一般说来一个应用程序的图形用户界面首先对应于一个复杂的容器,如一个窗口。这个容器内部将包含许多界面成分和元素,这些界面元素本身也可能又是一个容器,这个容器再进一步包含它的界面成分和元素,依此类推就构成一个复杂的图形界面系统。容器的引入有利于分解图形用户界面的复杂性,当界面的功能较多时,使用层层相套的容器是非常有必要的。\n2.控制组件与容器不同,控制组件是图形用户界面的最小单位之一,它里面不再包含其他的成分。控制组件的作用是完成与用户的一次交互,包括接收用户的一个命令(如菜单命令),接收用户的一个文本或选择输入,向用户显示一段文本或一个图形,等等。从某种程度上来说,控制组件是图形用户界面标准化的结果,目前常用的控制组件有选择类的单选按钮、复选按钮、下拉列表;有文字处理类的文本框、文本区域;有命令类的按钮、菜单等。其中文本框、按钮和标签是前面使用过的GUI组件。\n使用控制组件,通常需要如下的步骤:(1)创建某控制组件类的对象,指定其大小等属性。(2)使用某种布局策略,将该控制组件对象加入到某个容器中的某指定位置处。(3)将该组件对象注册给它所能产生的事件对应的事件监听者,重载事件处理方法,实现利用该组件对象与用户交互的功能。严格说来,容器也是一种控制组件,因为一个容器也可以被视为组件而包含在其他容器的内部。\n3.用户自定义成分除了上述的标准图形界面元素,编程人员还可以根据用户的需要设计一些用户自定义的图形界面成分,例如绘制一些几何图形、使用标志图案等。用户自定义成分由于不能像标准界面元素一样被系统识别和承认,所以通常只能起到装饰、美化的作用,而不能响应用户的动作,也不具有交互功能。\n7.2用户自定义成分本节主要介绍如何利用Java类库中的类及其方法来绘制用户自定义的图形界面成分。编程人员可以利用这些方法自由地绘制图形和文字,也可以将已经存在的图形、动画等加载到当前程序中来。绘制图形和文字将要用到前面已经接触过的类Graphics。\nGraphics是java.awt包中一个类,其中包括了很多绘制图形和文字的方法。当一个Applet运行时,执行它的浏览器会自动为它创建一个Graphics类的实例,利用这个实例,就可以在Applet中随意绘制图形和文字。实际上Applet本身就是一个图形界面的容器。而如果希望在图形界面的JavaApplication程序中绘制图形,则需要创建一个Canvas类的对象加入到这个Application程序的图形界面容器中,Canvas对象也拥有一个与Applet类的paint()方法相同的paint()方法,利用系统传递给这个paint()方法的Graphics类参数对象就可以在Application程序的图形用户界面中绘制各种图形和文字。\n7.2.1绘制图形利用Graphics类可绘制的图形有直线、各种矩形、多边形、圆和椭圆等。下面的例子综合了这些方法。例7-1DrawFigures.java1:importjava.awt.*;2:importjava.applet.Applet;3:publicclassDrawFiguresextendsApplet4:{5:publicvoidpaint(Graphicsg)6:{7:g.drawLine(30,5,40,5);//画直线\n8:g.drawRect(40,10,50,20);//画矩形框(左上角x坐标,左上角y坐标,x轴尺寸,y轴尺寸)9:g.fillRect(60,30,70,40);//画实心矩形10:g.drawRoundRect(110,10,130,50,30,30);//画圆角矩形框11:g.drawOval(150,120,70,40);//画椭圆形框(左上角x坐标,左上角y坐标,x轴尺寸,y轴尺寸),若x轴尺寸与y轴尺寸相等,则画出圆形12:g.fillOval(190,160,70,40);//画实心椭圆13:g.drawOval(90,100,50,40);//画椭圆框14:g.fillOval(130,100,50,40);//画实心椭圆15:drawMyPolygon(g);//自定义的画多边形的方法16:g.drawString(″Theyarefigures!″,100,220);\n17:}18:publicvoiddrawMyPolygon(Graphicsg)19:{20:int[]xCoords={30,50,65,119,127};//保存多边形各点x坐标的数组21:int[]yCoords={100,140,127,169,201};//保存多边形各点y坐标的数组22:g.drawPolygon(xCoords,yCoords,5);//画自由多边形框23:}24:}\n图7.1是例7-1的运行结果。从例7-1可以看出,要在Java程序图形界面的容器中绘制图形,首先,需要明确希望绘制的图形是什么,是圆、椭圆,还是直线,这由所选定的方法来确定;其次,需要指明所绘制图形或文字的大小和位置,这要通过相对于界面容器的二维像素坐标来决定。Java的屏幕坐标是以像素为单位,容器的左上角被确定为横坐标(x轴)和纵坐标(y轴)的起点,向右和向下延伸坐标值递增。\n图7.1例7-1的运行结果\n绘制图形的方法很多,每种方法一般也有多种灵活的使用方式,这里不再赘述,读者可以查阅程序员手册中的详细规定。除了Graphics类,Java中还定义了其他一些用来表示几何图形的类,对绘制用户自定义成分也很有帮助。例如,利用Point表示一个像素点;利用Dimension类表示宽和高;利用Rectangle类表示一个矩形;利用Polygon类表示一个多边形;利用Color类表示颜色等,后面的例子中将利用这些系统定义的类绘图。\n7.2.2显示文字从前面的例子中可以知道,Graphics类的方法drawString()可以在屏幕的指定位置显示一个字符串。Java中还有一个类Font,使用它可以获得更加丰富多彩和逼真精确的字体显示效果。一个Font类的对象表示了一种字体显示效果,包括字体类型、字型和字号。下面的语句用于创建一个Font类的对象:FontMyFont=newFont(″TimesRoman″,Font.BOLD,12);MyFont对应的是12磅TimesRoman类型的黑体字,其中指定字型时需要用到Font类的三个常量:Font.PLAIN,Font.BOLD,Font.ITALIC。\n如果希望使用该Font对象,则可以利用Graphics类的setFont()方法:g.setFont(MyFont);如果希望指定控制组件,如按钮或文本框中的字体效果,则可以使用控制组件的方法setFont()。如设btn是一个按钮对象,则语句:btn.setFont(MyFont);将把这个按钮上显示的标签的字体改为12磅的TimesRoman黑体字。另外,与setFont()方法相对的getFont()方法将返回当前Graphics或组件对象使用的字体。\n例7-2AvailableFonts.java1:importjava.applet.*;2:importjava.awt.*;3:4:publicclassAvailableFontextendsApplet5:{6:GraphicsEnvironmentgl=GraphicsEnvironment.getLocalGraphicsEnvironment();7:StringFontNames[]=gl.getAvailableFontFamilyNames();8:9:publicvoidpaint(Graphicsg)10:{\n11:Fontcurrent,oldFont;12:13:oldFont=g.getFont();14:for(inti=0;iUseColor

通过改变三个参数的数值(应在0~255之间),就可以指定不同的颜色而不需要重新编译JavaApplet程序。\n7.2.4显示图像由于图像的数据量要远远大于图形,所以一般不在程序中自行绘制图像,而是把已经存在于本机硬盘或网络某地的二进制图像文件直接调入内存。图像文件有多种格式,如bmp文件、gif文件、tiff文件等等,其中gif是Internet上常用的图像文件格式。Java中可以利用Graphics类的drawImage()方法显示图像,现考察下面的例子。例7-4DrawMyImage.java\n1:importjava.awt.*;2:importjava.applet.Applet;3:publicclassDrawMyImageextendsApplet4:{5:ImagemyImage;6:publicvoidinit()7:{8:myImage=getImage(getDocumentBase(),″blackbrd.gif″);9:}10:publicvoidpaint(Graphicsg)11:{\n12:g.drawImage(myImage,0,0,this);13:}14:}例7-4中,使用了Image类的对象myImage来保存二进制的图像数据,其中getImage()方法是系统为Applet类定义的方法,该方法将指定图像文件的内容加载到内存的Image对象中。getImage()方法有两个参数。第一个是图像文件所在的URL地址,在上例中由于图像文件与HTML文件保存在同一路径下,所以用Applet类另一个方法getDocumentBase()来获取含有该Applet的HTML文件的URL地址。getImage()的第二个参数是图像文件的文件名。Java可识别的图像文件格式有bmp,gif,jpeg等。\ndrawImage()是Graphics类中用来显示图像的方法。它的第一个参数是保存有图像数据的Image对象。第二、第三个参数是图像的左上角点坐标,它们决定了图像在容器中的显示位置。最后一个参数是显示图像的容器对象。例7-4中的this代表了当前的Applet对象。\n7.2.5实现动画效果动画曾是JavaApplet最吸引人的特性之一。用Java实现动画的原理与放映动画片类似,取若干相关的图像或图片,顺序、连续地在屏幕上先显示,后擦除,循环往复就可以获得动画的效果。参考下面的例子。例7-5ShowAnimator.java\n1:importjava.applet.Applet;2:importjava.awt.*;3:4:publicclassShowAnimatorextendsApplet5:{6:Image[]m-Images;//保存图片序列的Image数组7:inttotalImages=18;//图片序列中的图片总数8:intcurrentImage=0;//当前时刻应该显示的图片序号9:10:publicvoidinit()11:{12:m-Images=newImage[totalImages];\n13://从当前目录下的images子目录中将Img001.gif到Img0018.gif的文件加载14:for(inti=0;i=50)14:add(newButton(Integer.toString(i*6+j)));//随机加入按钮15:else16:add(newLabel());//随机加入空白17:}18:}19:}\n图7.18(b)是利用随机数随机地产生按钮或空白填充GridLayout的网格,把例7-17的语句:if((int)(Math.random()*100)>=50)改为:if((int)(Math.random()*100)>=0)得到的。图7.18(a)是所有区域全部填充为按钮的情况,从中可以清楚地看出GridLayout的布局策略和网格划分。\nGridBagLayout是五种布局策略中使用最复杂、功能最强大的一种,它是在GridLayout的基础上发展而来。因为GridLayout中的每个网格都是大小相同,并且强制组件与网格大小也相同,从而使得容器中的每个组件也都是相同的大小,显得很不自然,而且组件加入容器也必须按照固定的行列顺序,因此不够灵活。在GridBagLayout中,可以为每个组件指定其包含的网格个数,可以保留组件原来的大小,可以以任意顺序随意加入容器的任意位置,从而可以真正自由地安排容器中每个组件的大小和位置。\n7.11Panel与容器事件从本节开始,将详细讨论GUI各种容器及其使用方法。1.Container类Container类是一个抽象类,里面包含了所有容器组件都必须具有的方法和功能。(1)add():Container类中有多个经过重载的add()方法,其作用都是把Component组件,可能是一个基本组件,也可能是另一个容器组件,加入到当前容器中。每个被加入容器的组件根据加入的先后顺序获取一个序号。\n(2)getComponent(intindex)与getComponent(intx,inty):这两个方法分别获得指定序号或指定(x,y)坐标点处的组件。(3)remove(Component)与remove(intindex):将指定的组件或指定序号的组件从容器中移出。(4)removeAll():将容器中所有的组件移出。(5)setLayout():设置容器的布局编辑器。\nContainer可以引发ContainerEvent类代表的容器事件。当容器中加入或移出一个组件时,容器将分别引发COMPONENT-ADDED和COMPONENT-REMOVED两种容器事件。希望响应容器事件的程序应该实现容器事件的监听者接口ContainerListener,并在监听者内部具体实现该接口中用来处理容器事件的两个方法。publicvoidcomponentAdded(ContainerEvente);//响应向容器中加入组件事件的方法publicvoidcomponentRemoved(ContainerEvente);//响应从容器中移出组件的方法\n在这两个方法内部,可以调用实际参数e的方法e.getContainer()获得引发事件的容器对象的引用,这个方法的返回类型为Container;也可以调用e.getChild()方法获得事件发生时被加入或移出容器的组件,这个方法的返回类型为Component。\n2.容器事件(ContainerEvent)ContainerEvent类包含两个具体的与容器有关的事件:(1)COMPONENT-ADDED:把组件加入当前容器对象。(2)COMPONENT-REMOVED:把组件移出当前容器对象。ContainerEvent类的主要方法有:(1)publicContainergetContainer():返回引发容器事件的容器对象。(2)publicComponentgetChild():返回引发容器事件时被加入或移出的组件对象。\n3.PanelPanel属于无边框容器。无边框容器包括Panel和Applet,其中Panel是Container的子类,Applet是Panel的子类。\nPanel是最简单的容器,它没有边框或其他的可见的边界,它不能被移动、放大、缩小或关闭。一个程序不能使用Panel作为它的最外层的图形界面的容器,所以Panel总是作为一个容器组件被加入到其他的容器,如Frame,Applet等中去。Panel也可以进一步包含另一个Panel,使用Panel的程序中总是存在着容器的嵌套。使用Panel的目的通常是为了层次化管理图形界面的各个组件,同时使组件在容器中的布局操作更为方便。程序不能显式地指定Panel的大小,Panel的大小是由其中包含的所有组件,以及包容它的那个容器的布局策略和该容器中的其他组件决定的。\n例7-18TestPanel.javaimportjava.awt.*;importjava.applet.*;importjava.awt.event.*;publicclassTestPanelextendsAppletimplementsActionListener,ContainerListener{Panelp1,p2,p3;Labelprompt1,prompt2,prompt3;Buttonbtn;publicvoidinit(){p1=newPanel();\np1.setBackground(Color.gray);p2=newPanel();p2.setBackground(Color.red);p3=newPanel();p3.setBackground(Color.cyan);prompt1=newLabel(″我在第一个Panel里″);prompt2=newLabel(″我在第二个Panel里″);prompt3=newLabel(″我在第三个Panel里″);btn=newButton(″inPanel3″);p1.add(prompt1);p2.add(prompt2);p3.add(prompt3);p3.add(btn);p1.add(p3);\nadd(p1);add(p2);btn.addActionListener(this);p1.addContainerListener(this);}publicvoidactionPerformed(ActionEvente){if(e.getSource()==btn)p1.remove(p3);}publicvoidcomponentRemoved(ContainerEvente){showStatus(″您移去了第三个Panel″);}\npublicvoidcomponentAdded(ContainerEvente){}}图7.19是例7-18的运行结果。容器的嵌套是Java程序GUI界面设计和实现中经常需要使用到的手段,实现这一类GUI界面时,应该首先明确各容器之间的包含嵌套关系。例如,例7-18中的程序GUI存在如下的包含层次关系(图7.20)。\n图7.19例7-18的运行结果\n图7.20多容器图形界面的结构层次关系\n由于这个程序是一个JavaApplet,所以程序最外层的容器是一个Applet,其中包含了两个组件:第一个组件是一个Panel对象p1;第二个组件是另一个Panel对象p2,p1中包含了一个标签prompt1和第三个Panel对象p3;p3中包含一个标签prompt3和一个按钮btn。这里所有的容器都使用缺省的FlowLayout布局策略。当用户单击按钮btn时,程序从p1移去组件p3并引发CONTAINER-REMOVED事件,程序响应这个事件后在状态条中显示移去组件容器的信息。\nApplet是一种特殊的Panel,它是JavaApplet程序的最外层容器,但是JavaApplet并不是完整独立的程序,它事实上是WWW浏览器中的一个控件,是作为浏览器的一部分依赖于浏览器而存在的,所以JavaApplet可以依赖浏览器的窗口来完成放大、缩小、关闭等功能。至于JavaApplet程序本身,它只要负责它所拥有的Applet容器中的那部分无边框区域就足够了。Applet容器的缺省布局策略与其父类Panel一致,都是FlowLayout,但是Applet容器中还额外定义了一些用来与浏览器交互的方法,如init(),start(),stop()等。\n7.12Frame与窗口事件除了Applet和Panel这组无边框容器,Container还有一组有边框的容器的子类,包括Window,Frame,Dialog和FileDialog,其中Window是所有有边框容器的父类,但是Window本身并无边框,算是有边框容器的一个例外。这一组里的其他容器都是有边框可独立存在的容器。\n1.Frame在前面的例子中已经使用过Frame这种容器,它是Java中最重要、最常用的容器之一,是JavaApplication程序的图形用户界面容器。Frame可以作为一个Application的最外层容器,也可以被其他容器创建并弹出成为独立的容器,但是无论哪种情况,Frame都作为最顶层容器存在,不能被其他容器所包含。\nFrame有自己的外边框和自己的标题,创建Frame时可以指定其窗口标题。Frame(Stringtitle);也可以使用专门的方法getTitle()和setTitle(String)来获取或指定Frame的标题。新创建的Frame是不可见的,需要使用setVisible(boolean)方法,并使用实际参数true使之可见。\n每个Frame在其右上角都有三个控制图标(如图7.21所示),分别代表将窗口最小化、最大化和关闭的操作,其中最小化和最大化操作Frame可自动完成,而关闭窗口的操作不能通过点击关闭图标实现,需要程序专门书写有关的代码。常用的关闭窗口的方法有三个:一个是设置一个按钮,当用户点击按钮时关闭窗口;第二个方法是对WINDOWS-CLOSING事件做出响应,关闭窗口;第三个方法是使用菜单命令。前一种方法需要专门的按钮,而后一种方法实现WindowListener接口所需的代码较多,无论使用何种方法,都需要用到关闭Frame的dispose()方法。\n向Frame窗口中添加和移出组件使用的方法与其他容器相同,也是add()和remove(),Frame可以引发WindowEvent类代表的所有七种窗口事件。2.窗口事件(WindowEvent)WindowEvent类包含如下几个具体窗口事件。(1)WINDOW-ACTIVATED:代表窗口被激活(在屏幕的最前方待命)。(2)WINDOW-DEACTIVATED:代表窗口失活(其他窗口被激活后原活动窗口失活)。(3)WINDOW-OPENED:代表窗口被打开。(4)WINDOW-CLOSED:代表窗口已被关闭(指已关闭后)。\n(5)WINDOW-CLOSING:代表窗口正在被关闭(指关闭前,如点击窗口的关闭按钮)。(6)WINDOW-ICONIFIED:代表使窗口最小化成图标。(7)WINDOW-DEICONIFIED:代表使窗口从图标恢复。WindowEvent类的主要方法有publicwindowgetWindow();此方法返回引发当前WindowEvent事件的具体窗口,与getSource()方法返回的是相同的事件引用;但是getSource()的返回类型为Object,而getWindow()方法的返回值是具体的Window对象。\n例7-19TestFrame.java1:importjava.awt.*;2:importjava.awt.event.*;3:4:publicclassTestFrame5:{6:publicstaticvoidmain(Stringargs[])7:{8:newMyFrame();9:}10:}11:classMyFrameextendsFrameimplementsActionListener12:{\n13:Buttonbtn;14:MyFrame()15:{16:super(″我的窗口″);17:btn=newButton(″关闭″);18:setLayout(newFlowLayout());19:add(btn);20:btn.addActionListener(this);21:addWindowListener(newcloseWin());22:setSize(300,200);23:setVisible(true);24:}25:publicvoidactionPerformed(ActionEvente)\n26:{27:if(e.getActionCommand()==″关闭″)28:{29:dispose();30:System.exit(0);31:}32:}33:}34:classcloseWinextendsWindowAdapter35:{36:publicvoidwindowClosing(WindowEvente)//监听到事件,关闭事件源窗口37:{\n38:Framefrm=(Frame)(e.getSource());39:frm.dispose();40:System.exit(0);41:}42:}图7.21是例7-19的运行结果。\n图7.21例7-19的运行结果\n这是一个图形界面的JavaApplication程序。程序里定义了三个类,closeWin是窗口事件的剪裁类WindowAdapter的子类,重载了windowClosing()方法来关闭被用户单击关闭图标按钮的事件源窗口。MyFrame是用户定义的系统类Frame的子类,里面包括一个按钮btn,用户单击这个按钮时将关闭这个MyFrame对象。主类TestFrame的main()方法里所创建的MyFrame的对象就是这个Application的图形界面窗口。\n7.13菜单的定义与使用关于Frame容器,还需要讨论的一点就是Frame是可以拥有菜单的容器,它实现了MenuContainer接口。菜单是非常重要的GUI组件,每个菜单组件包括一个菜单条,称为MenuBar。每个菜单条又包含若干个菜单项,称为Menu。每个菜单项再包含若干个菜单子项,称为MenuItem。每个菜单子项的作用与按钮相似,也是在用户点击时引发一个动作命令,所以整个菜单就是一组经层次化组织、管理的命令集合;使用它,用户可以方便地向程序发布指令。参看下面的例7-20。\n例7-20TestMenu.java1:importjava.awt.*;2:importjava.awt.event.*;3:4:publicclassTestMenu//定义主类5:{6:publicstaticvoidmain(Stringargs[])7:{8:MyMenuFramemf=newMyMenuFrame();9:mf.setSize(newDimension(300,200));//用setSize()方法指定窗口的初始大小10:mf.setVisible(true);//使窗口可见\n11:}12:}13:14:classMyMenuFrameextendsFrame15:implementsActionListener,ItemListener//定义窗口16:{17:MenuBarm-MenuBar;18:MenumenuFile,menuEdit,m-Edit-Paste;19:MenuItemmi-File-Open,mi-File-Close,mi-File-Exit,mi-Edit-Copy;20:MenuItempi-New,pi-Del,pi-Pro,mi-Paste-All,mi-Paste-Part;21:CheckboxMenuItemmi-Edit-Cut;22:PopupMenupopM;\n23:TextAreata;24:25:MyMenuFrame()//构造函数26:{27:super(″拥有菜单的窗口″);//指定窗口标题28:ta=newTextArea(″\n\n\n\n\n\n\t\t\t没有选择″,5,20);29:ta.addMouseListener(newHandleMouse(this));//文本域响应鼠标事件30:add(″Center″,ta);31:32:popM=newPopupMenu();//创建弹出窗口33:pi-New=newMenuItem(″新建″);//为弹出窗口创建菜单子项\n34:pi-New.addActionListener(this);//使菜单子项响应动作事件35:popM.add(pi-New);//为弹出菜单加入菜单子项36:pi-Del=newMenuItem(″删除″);37:pi-Del.addActionListener(this);38:popM.add(pi-Del);39:pi-Pro=newMenuItem(″属性″);40:pi-Pro.addActionListener(this);41:popM.add(pi-Pro);42:ta.add(popM);//将弹出窗口加在文本域上43:44:m-MenuBar=newMenuBar();//创建菜单条45:\n46:menuFile=newMenu(″文件″);//创建菜单项,创建菜单子项并指定快捷键47:mi-File-Open=newMenuItem(″打开″,newMenuShortcut(′o′));48:mi-File-Close=newMenuItem(″关闭″);49:mi-File-Exit=newMenuItem(″退出″);50:mi-File-Exit.setShortcut(newMenuShortcut(′x′));//设置菜单子项的快捷键51:mi-File-Open.setActionCommand(″打开″);//再设置命令名52:mi-File-Exit.setActionCommand(″退出″);//以便动作响应程序调用53:mi-File-Open.addActionListener(this);//使菜单子项响应动作事件54:mi-File-Close.addActionListener(this);\n55:mi-File-Exit.addActionListener(this);56:menuFile.add(mi-File-Open);//把菜单子项加入菜单项57:menuFile.add(mi-File-Close);58:menuFile.addSeparator();//加一条横向分割线59:menuFile.add(mi-File-Exit);60:m-MenuBar.add(menuFile);//把菜单项加入菜单条61:62:menuEdit=newMenu(″编辑″);63:mi-Edit-Copy=newMenuItem(″复制″);64:mi-Edit-Cut=newCheckboxMenuItem(″剪切″);//创建选择菜单子项65:m-Edit-Paste=newMenu(″粘贴″);//创建二级菜单项\n66:mi-Paste-All=newMenuItem(″全部粘贴″);67:mi-Paste-Part=newMenuItem(″部分粘贴″);68:mi-Edit-Copy.addActionListener(this);69:mi-Edit-Cut.addItemListener(this);//检测盒菜单子项产生选择事件70:m-Edit-Paste.add(mi-Paste-Part);//为二级菜单项加入菜单子项71:m-Edit-Paste.add(mi-Paste-All);72:mi-Paste-Part.addActionListener(this);73:mi-Paste-All.addActionListener(this);74:menuEdit.add(mi-Edit-Copy);75:menuEdit.add(mi-Edit-Cut);76:menuEdit.addSeparator();\n77:menuEdit.add(m-Edit-Paste);//把二级菜单项加入菜单项78:m-MenuBar.add(menuEdit);79:80:this.setMenuBar(m-MenuBar);//把菜单条加入整个Frame容器81:}82:publicvoidactionPerformed(ActionEvente)//响应动作事件83:{84:if(e.getActionCommand()==″退出″)//选择″退出″菜单则关闭窗口退出程序85:{86:dispose();87:System.exit(0);88:}\n89:else//否则显示选择的命令名90:ta.setText(″\n\n\n\n\n\n\t\t\t″+e.getActionCommand());91:}92:publicvoiditemStateChanged(ItemEvente)//响应CheckboxMenuItem单击事件93:{94:if(e.getSource()==mi-Edit-Cut)95:if(((CheckboxMenuItem)e.getSource()).getState())//查看是否选中96:ta.setText(″\n\n\n\n\n\n\t\t\t″+″选择了″//因为无命令名,所以用标签97:+((CheckboxMenuItem)e.getSource()).getLabel());\n98:else99:ta.setText(″\n\n\n\n\n\n\t\t\t″+″未选择″100:+((CheckboxMenuItem)e.getSource()).getLabel());101:}102:}103:104:classHandleMouseextendsMouseAdapter//处理鼠标事件类,继承鼠标事件裁剪类105:{106:MyMenuFramem-Parent;//产生事件的组件所在的窗口容器107:\n108:HandleMouse(MyMenuFramemf)//构造函数109:{110:m-Parent=mf;111:}112:publicvoidmouseReleased(MouseEvente)//鼠标按键松开事件弹出菜单113:{114:if(e.isPopupTrigger())//检查鼠标事件是否是由弹出菜单引发的115:m-Parent.popM.show((Component)e.getSource(),e.getX(),e.getY());116:}//将弹出菜单显示在用户鼠标点击的位置117:}\n例7-20使用了Java中提供的大部分关于菜单的功能,Java中的菜单分为两大类:一类是菜单条式菜单,通常称的菜单就是指这类菜单;另一类是弹出式菜单。下面先讨论菜单条式菜单的实现与使用。1.菜单的设计与实现菜单的设计与实现步骤如下:(1)创建菜单条MenuBar。例如下面的语句创建了一个空的菜单条。m-MenuBar=newMenuBar();\n(2)创建不同的菜单项Menu加入到空菜单条中。下面的语句创建了一个菜单项并把它加入到菜单条中,菜单项的标题为“编辑”。menuEdit=newMenu(″编辑″);m-MenuBar.add(menuEdit);(3)为每个菜单项创建其所包含的更小的菜单子项MenuItem,并把菜单子项加入到菜单项中去。mi-Edit-Copy=newMenuItem(″复制″);menuEdit.add(mi-Edit-Copy);\n(4)将整个建成的菜单条加入到某个容器中去。this.setMenuBar(m-MenuBar);这里的this代表程序的容器Frame,需要注意的是并非每个容器都可以配菜单条式菜单,只有实现了MenuContainer接口的容器才能加入菜单。(5)上面的这些工作主要是为了组建菜单的结构,如有哪些菜单项,哪些菜单子项,等,但如何定义各个菜单子项所对应的命令和操作呢?首先要将各菜单子项注册给实现了动作事件的监听接口ActionListener的监听者,如,例7-20中的容器。mi-Edit-Copy.addActionListener(this);\n(6)为监听者定义actionPerformed(ActionEvente)方法,在这个方法中调用e.getSource()或e.getActionCommand()来判断用户点击的菜单子项,并完成这个子项定义的操作。创建好的菜单条式菜单位于窗口的上方,图7.22就显示了例7-20中创建的菜单条。\n图7.22拥有菜单条的Frame窗口\n2.使用分隔线有时希望在菜单子项之间增加一条横向分隔线,以便把菜单子项分成几组。加入分隔线的方法是Menu的方法addSeparator(),使用时要注意该语句的位置。菜单子项是按照加入的先后顺序排列在菜单项中的,希望把分隔线加在哪里,就要把分隔线语句放在哪里。例如,在“文件”菜单项中用如下的语句加入了一条分隔线(参看图7.22)。menuFile.addSeparator();//加一条横向分隔线\n3.使用菜单子项快捷键除了用鼠标选择菜单子项,还可以为每个菜单子项定义一个键盘快捷键,这样用键盘一样可以选择菜单子项。快捷键是一个字母,定义好后按住Ctrl键和这个字母就可以选中对应的菜单子项。为菜单子项定义快捷键有两种方法:一种是在创建菜单子项的同时定义快捷键。MenuItemmi-File-Open=newMenuItem(″打开″,newMenuShortcut(′o′));\n另一种是为已经存在的菜单子项定义快捷键。mi-File-Exit.setShortcut(newMenuShortcut(′x′));//单独设置菜单子项的快捷键设置后菜单子项“打开”对应快捷键Ctrl+O,菜单子项“退出”对应Ctrl+X,参见图7.22。\n4.使用二级菜单如果希望菜单子项还能够进一步再引出更多的菜单项,可以使用二级菜单。二级菜单的使用方法很简单,创建一个包含若干菜单子项(MenuItem)的菜单项(Menu),把这个菜单项像菜单子项一样加入到一级菜单项中即可。m-Edit-Paste=newMenu(″粘贴″);//创建二级菜单项mi-past-All=newMenuItem(″全部粘贴″);mi-past-Part=newMenuItem(″部分粘贴″);m-Edit-Paste.add(mi-Paste-Part);//为二级菜单项加入菜单子项m-Edit-Paste.add(mi-Paste-All);menuEdit.add(m-Edit-Paste);//把二级菜单项加入菜单项\n二级菜单的使用效果如图7.23所示。图7.23二级菜单与检测盒菜单子项\n5.使用检测盒菜单子项Java中还定义了一种特殊的菜单子项,称为检测盒菜单子项CheckboxMenuItem。这种菜单子项与检测盒一样,有“选中”和“未选中”两种状态,每次选择这类菜单子项都使它在这两种状态之间切换,处于“选中”状态的检测盒菜单子项的前面有一个小对号(如图7.23所示),处于“未选中”状态时没有这个小对号。创建检测盒菜单子项并把它加入菜单项的方法为:mi-Edit-Cut=newCheckboxMenuItem(″剪切″);//创建选择菜单子项menuEdit.add(mi-Edit-Cut);\n选择检测盒菜单子项引发的事件不是动作事件ActionEvent,而是选择事件ItemEvent,所以需要把检测盒菜单子项注册给ItemListener,并具体实现ItemListener的itemStateChanged(ItemEvente)事件,与响应检测盒的事件较为相似。mi-Edit-Cut.addItemListener(this);\n6.使用弹出式菜单弹出式菜单附着在某一个组件或容器上,一般它是不可见的,只有当用户用鼠标右键点击附着有弹出式菜单的组件时,这个菜单才“弹出”来显示。弹出式菜单与菜单条式菜单一样,也包含若干个菜单子项,创建弹出式菜单并加入菜单子项的操作如下:PopupMenupopM=newPopupMenu();//创建弹出窗口MenuItempi-New=newMenuItem(″新建″);//为弹出窗口创建菜单子项pi-New.addActionListener(this);//使菜单子项响应动作事件\npopM.add(pi-New);//为弹出菜单加入菜单子项然后需要把弹出式菜单附着在某个组件或容器上。ta.add(popM);//将弹出窗口加在文本域上用户点击鼠标右键时弹出式菜单不会自动显示出来,还需要一定的程序处理,首先把附着有弹出菜单的组件或容器注册给MouseListener。ta.addMouseListener(newHandleMouse(this));//文本域响应鼠标事件,弹出菜单然后重载MouseListener的mouseReleased(MouseEvente)方法。在这个方法里调用弹出式菜单的方法show()把它自身显示在用户鼠标点击的位置。\npublicvoidmouseReleased(MouseEvente)//鼠标按键松开事件弹出菜单{if(e.isPopupTrigger())//检查鼠标事件是否由弹出菜单引发m-Parent.popM.show((Component)e.getSource(),e.getX(),e.getY());}//将弹出菜单显示在用户鼠标点击的位置这里方法e.getSource()返回的是附着有弹出式菜单的组件或容器,弹出式菜单应该显示在这个组件或容器中鼠标点击的位置(由e.getX()方法和e.getY()方法确定鼠标点击的坐标位置),如图7.24所示。\n图7.24弹出式菜单的显示与使用\n7.14对话框、组件事件与焦点事件1.组件事件(ComponentEvent)这个类是所有低级事件的根类,一共包含四个具体事件,可以用ComponentEvent类的几个静态常量来表示。(1)ComponentEvent.COMPONENT-HIDDEN:代表隐藏组件的事件。(2)ComponentEvent.COMPONENT-SHOWN:代表显示组件的事件。(3)ComponentEvent.COMPONENT-MOVED:代表移动组件的事件。\n(4)ComponentEvent.COMPONENT-RESIZED:代表改变组件大小的事件。把调用getID()方法的返回值与上述常量相比较,就可以知道ComponentEvent对象所代表的具体事件。\n2.焦点事件(FocusEvent)FocusEvent类包含两个具体事件,分别对应这个类的两个同名静态整型常量。(1)FOCUS-GAINED:代表获得了注意的焦点。(2)FOCUS-LOST:代表失去了注意的焦点。一个GUI的对象必须首先获得注意的焦点,才能被进一步操作。例如,一个文本输入区域必须首先获得注意的焦点,才能接受用户键入的文字。一个窗口只有先获得了注意的焦点,其中的菜单才能被选中等。获得注意的焦点将使对象被调到整个屏幕的最前面并处于待命的状态,是缺省操作的目标对象,而失去注意焦点的对象则被调到屏幕的后面并可能被其他的对象遮挡。\n3.对话框(Dialog)与Frame一样,Dialog是有边框、有标题的独立存在的容器,并且不能被其他容器所包容;但是Dialog不能作为程序的最外层容器,也不能包含菜单条。与Window一样,Dialog必须隶属于一个Frame并由这个Frame负责弹出。Dialog通常起到与用户交互的对话框的作用,例如向用户报告消息并要求确认的消息对话框,接受用户输入的一般对话框等。Dialog的构造函数有四种重载方式,其中最复杂的为:Dialog(Frameparent,Stringtitle,booleanisModal)\n第一个参数指明新创建的Dialog对话框隶属于哪个Frame窗口,第二个参数指明新建Dialog对话框的标题,第三个参数指明该对话框是否是有模式的。所谓“有模式”的对话框,是那种一旦打开后用户必须对其做出响应的对话框,例如对话框询问用户是否确认删除操作,此时程序处于暂停状态,除非用户回答了对话框的问题,否则是不能使用程序的其他部分的,所以带有一定的强制性质;而无模式对话框则没有这种限制,用户完全可以不理会这个打开的对话框而去操作程序的其他部分,缺省情况下对话框都是无模式的。新建的对话框使用缺省的BorderLayout,它是不可见的,可以使用show()方法显示它。\n对于已经创建的对话框,还可以用setModal(booleanisModal)方法来改变其模式属性,或者使用booleanisModal()方法来判断它是否是一个有模式对话框。另外,Dialog还有获得和修改其对话框标题的方法getTitle()和setTitle(StringnewTitle);还有加入和移出组件的方法add(Component)和remove(Component)。先来看一个用Dialog实现的消息对话框和一般对话框的例子。\n例7-21TestDialog.java1:importjava.awt.*;2:importjava.awt.event.*;3:4:publicclassTestDialog//定义JavaApplication主类5:{6:publicstaticvoidmain(Stringargs[])7:{8:MyDialogFramedf=newMyDialogFrame();9:}10:}11:\n12:classMyDialogFrameextendsFrame13:implementsActionListener,ComponentListener,FocusListener14:{15:DialogMegDlg,InOutDlg;//对话框隶属于Frame16:Buttonbtn1,btn2,btnY,btnN,btnR;17:TextFieldtf=newTextField(″没有信息″,45);18:TextFieldgetMeg=newTextField(″输入信息″,10);19:20:MyDialogFrame()//构造函数21:{22:super(″使用对话框″);23:btn1=newButton(″隐藏″);24:btn2=newButton(″询问″);\n25:btnY=newButton(″是″);26:btnN=newButton(″否″);27:btnR=newButton(″返回″);28:setLayout(newFlowLayout());29:add(tf);30:add(btn1);31:add(btn2);32:btn1.addComponentListener(this);33:this.addWindowListener(newWinAdpt());//Frame响应窗口关闭事件34:btn1.addActionListener(this);35:btn2.addActionListener(this);36:btnY.addActionListener(this);37:btnN.addActionListener(this);\n38:btnR.addActionListener(this);39:setSize(350,150);//改变Frame尺寸40:show();//显示原来不可见的Frame41:}42:publicvoidactionPerformed(ActionEvente)//响应按钮引发的动作事件43:{44:if(e.getActionCommand()==″隐藏″)//按“隐藏”按钮将隐藏此按钮本身45:{//创建″有模式″的消息对话框向用户确认删除操作46:MegDlg=newDialog(this,″真要隐藏吗?″,true);\n47:Panelp1=newPanel();48:p1.add(newLabel(″此操作将隐藏该按钮,要继续吗?″));49:MegDlg.add(″Center″,p1);50:Panelp2=newPanel();51:p2.add(btnY);52:p2.add(btnN);53:MegDlg.add(″South″,p2);54:MegDlg.setSize(200,100);55:MegDlg.show();//显示对话框56:}57:elseif(e.getActionCommand()==″询问″)58:{//创建″无模式″的对话框接受用户输入的信息\n59:InOutDlg=newDialog(this,″请输入信息″);60:InOutDlg.add(″Center″,getMeg);61:InOutDlg.add(″South″,btnR);62:InOutDlg.setSize(200,100);63:InOutDlg.addFocusListener(this);64:InOutDlg.show();65:}66:elseif(e.getActionCommand()==″是″)//用户对消息对话框中的按钮的响应67:{68:MegDlg.dispose();//关闭消息对话框69:btn1.setVisible(false);//确认隐藏,引发组件事件70:}\n71:elseif(e.getActionCommand()==″否″)//用户对消息对话框中的按钮的响应72:MegDlg.dispose();//取消隐藏操作,关闭对话框73:elseif(e.getActionCommand()==″返回″)//用户对输入输出对话框中按钮的响应74:{//获取用户在对话框的输入并显示在Frame中75:tf.setText(getMeg.getText()+″是对话框的输入″);76:InOutDlg.dispose();//关闭输入输出对话框77:}78:}79:publicvoidcomponentShown(ComponentEvente){}//实现ComponentListener中方法80:publicvoidcomponentResized(ComponentEvente){}\n81:publicvoidcomponentMoved(ComponentEvente){}82:publicvoidcomponentHidden(ComponentEvente)//当按钮被隐藏时,显示相关信息83:{84:tf.setText(″按钮\″″+((Button)e.getComponent()).getLabel()+″\″被隐藏!″);85:}86:publicvoidfocusGained(FocusEvente)87:{88:getMeg.setText(″对话框\″″+((Dialog)e.getComponent()).getTitle()89:+″\″获得了注意的焦点!″);90:}\n91:publicvoidfocusLost(FocusEvente){}92:}93:classWinAdptextendsWindowAdapter//创建窗口剪裁类子类,处理窗口关闭事件94:{95:publicvoidwindowClosing(WindowEvente)96:{97:((Frame)e.getWindow()).dispose();//获得引发事件的窗口并关闭之98:System.exit(0);99:}100:}\n这个程序的最外层容器是一个Frame窗口,它可以响应动作事件和容器事件。窗口中包含一个文本框和两个按钮。用户点击第一个按钮“隐藏”时,弹出消息对话框MegDlg。其中包含一个Label询问用户是否确实要隐藏第一个按钮,还包含两个按钮“是”和“否”。如果用户按“否”,则关闭此对话框;如果按“是”,则关闭对话框并隐藏第一个按钮,此时隐藏按钮的操作将引发组件事件把相关信息显示在Frame的文本框tf中。\n用户点击Frame的第二个按钮“询问”时,弹出输入输出对话框InOutDlg,请用户在这个对话框的文本框中输入信息。InOutDlg对话框可以响应获得注意焦点的事件,当用户输入并按“返回”按钮时,关闭此对话框并把其文本框getMeg中的信息传送回Frame的文本框tf显示。程序运行结果如图7.25所示。Dialog还有一个子类FileDialog,用来表示一种特殊的用来搜索目录和文件,并打开或保存特定文件的对话框,将在后面结合Java的文件操作介绍FileDialog的使用方法。\n图7.25例7-21的运行结果\n7.15小结本章介绍图形用户界面的Java编程方法,主要介绍java.awt和java.awt.event两个包的使用。7.1节概述了图形用户界面的基础知识,主要包括图形界面的构成。7.2节介绍了图形界面中用户自定义成分的绘制,包括绘制图形,显示文字和图像,控制颜色以及实现动画效果等。7.3节介绍Java的委托事件处理机制的基本原理,7.4节简述java.awt包中的标准GUI组件。从7.5节开始详细介绍每种组件的创建、使用与事件处理,包括文本框、文本区域、各种选择组件、滚动条和按钮等。7.10节介绍Java的常用布局策略。7.11节到7.14节介绍了Java的主要容器组件,包括Panel,Frame,Dialog等。\n习题7-1什么是图形用户界面?它与字符界面有何不同?你是否曾使用过这两种界面?试列举出图形用户界面中你使用过的组件。7-2简述图形界面的构成成分,它们各自的作用。设计和实现图形用户界面的工作主要有哪两个?7-3Java程序的图形用户界面中有哪些用户自定义成分?7-4编写Applet程序,画出一条螺旋线。\n7-5编写Applet程序,用paint()方法显示一行字符串,Applet包含两个按钮“放大”和“缩小”,当用户单击“放大”时显示的字符串字体放大一号,单击“缩小”时显示的字符串字体缩小一号。7-6编写Applet程序,包含三个标签,其背景分别为红、黄、蓝三色。7-7改写例7-4,让用户输入欲显示.gif文件名,程序将这个图像文件加载到内存并显示。7-8改写例7-5,在Applet中增加两个按钮“左旋”和“右旋”,用户单击这两个按钮时动画中的图像向相应的方向旋转。\n7-9简述Java的事件处理机制和委托事件模型。什么是事件源?什么是监听者?Java的图形用户界面中,谁可以充当事件源?谁可以充当监听者?7-10列举java.awt.event包中定义的事件类,并写出它们的继承关系。7-11列举GUI的各种标准组件和它们之间的层次继承关系。使用标准组件的基本步骤是什么?7-12Component类有何特殊之处?其中定义了哪些常用方法?7-13将各种常用组件的创建语句、常用方法、可能引发的事件、需要注册的监听者和监听者需要重载的方法综合在一张表格中画出。\n7-14动作事件的事件源可以有哪些?如何响应动作事件?7-15编写Applet包括一个标签、一个文本框和一个按钮,当用户单击按钮时,程序把文本框中的内容复制到标签中。7-16文本框与文本区域在创建方法、常用方法和事件响应上有何异同?什么操作将引发文本事件?如何响应文本事件?编写Applet包含一个文本框、一个文本区域和一个按钮,当用户单击按钮时,程序将文本区域中被选中的字符串复制到文本框中。7-17什么是选择事件?哪些操作将引发选择事件?可能产生选择事件的GUI组件有哪些?它们之间有什么异同?分别适合于什么场合?\n7-18将例7-8、7-9、7-10综合成一个程序,使用Checkbox标志按钮的背景色,使用CheckboxGroup标志三种字体风格,使用Choice选择字号,使用List选择字体名称,由用户确定按钮的背景色和前景字符的显示效果。7-19什么是调整事件?调整事件与选择事件有何不同?什么是滚动条?如何创建和使用滚动条?编写一个Applet包含一个滚动条,在Applet中绘制一个圆,用滚动条滑块显示的数字表示该圆的直径,当用户拖动滑块时,圆的大小随之改变。7-20编写一个Applet响应鼠标事件,用户可以通过拖动鼠标在Applet中画出矩形,并在状态条显示鼠标当前的位置。\n7-21改写7-20题,使用一个Vector对象保存用户所画过的每个矩形并显示、响应键盘事件,当用户击键′q′时清除屏幕上所有的矩形。7-22改写7-18题的程序,使用一个Canvas及其上的字符串,来显示各选择组件确定的显示效果。7-23什么是容器的布局策略?试列举并简述Java中常用的几种布局策略。7-24编写Applet程序实现一个计算器,包括十个数字(0~9)按钮和四个运算符(加、减、乘、除)按钮,以及等号和清空两个辅助按钮,还有一个显示输入输出的文本框。试分别用BorderLayout和GridLayout实现。\n7-25Panel与Applet有何关系?Panel在Java程序里通常起到什么作用?7-26为什么说Frame是非常重要的容器?为什么使用Frame的程序通常要实现WindowListener?关闭Frame有哪些方法?7-27将7-15题改写为图形界面的Application程序。7-28利用Canvas对象,将7-19题的程序改写为图形界面的Application程序。7-29常用的菜单有哪两类?是不是任何容器都可以使用菜单?简述实现菜单的编程步骤。\n7-30编写图形界面的Application程序,包含一个菜单,选择这个菜单的“退出”选项可以关闭Application的窗口并结束程序。7-31扩充7-30题的程序,使Application窗口中包含一个文本区域和一个按钮,文本区域中事先包含一段文字,利用焦点监听者和文本监听者实现如下功能:当用户修改了文本框中的内容并试图离开这个文本框时,程序弹出有模式对话框请用户确认修改;如果用户只是进入并退出文本框而没有修改其中的内容,则不会弹出对话框。7-32根据本章的所学习的内容用JavaApplication编写一个模拟的文字编辑器。

相关文档