版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第4章图形界面4.1Applet与图形界面4.2图形输出4.3图形用户界面设计4.4图形界面应用程序
4.1Applet与图形界面
4.1.1案例1:显示图像文件的Applet
前面各章大部分例子都是Java应用程序。Java应用程序可通过System.out向标准输出设备输出文本,而Java小程序不能通过此种方法输出信息。Java小程序在浏览器中运行,占据页面中的一块矩形区域,信息的输出必须通过Java语言提供的图形功能画在此矩形区域。
本节案例要求实现一个Applet,先显示一幅图像文件,单击该图像后,将显示另一幅图像。图4.1和图4.2为使用JBuilder调试程序的运行画面。图4.1显示第一幅图像图4.2单击后显示第二幅图像4.1.2Applet程序结构
Applet程序在支持Java的Web浏览器中执行,它的结构不同于Java应用程序。每一个Applet都有一个主类,派生自java.applet.Applet。
与Java应用程序不同,在Applet程序中看不到明显的程序执行流程。在第1章Applet的例子中,只写了一个paint方法,该方法与应用程序的main方法不同。当paint方法执行结束后,Applet并没有中止执行,而当Applet需要重新绘制时,paint方法再次被调用。实际上,Applet的执行流程在其超类java.applet.Applet中已确定,当需要绘制Applet占据的矩形空间时,即调用paint方法,而在我们所写的Applet中已覆盖了原Applet类中定义的paint方法,因此当需要绘制Applet时,派生类中定义的paint即被调用。
在Applet类中定义了几个重要的方法,这几个方法在Applet整个运行的生命周期中具有特殊的作用,在编写Applet时应根据需要覆盖对应的方法。下面简要介绍这几种方法。
1) publicvoidinit()
init方法的作用是初始化。在整个Applet生命周期中,初始化只进行一次。当Web浏览器第一次浏览含有Applet的网页时,浏览器首先下载该Applet字节码文件,然后创建一个该Applet主类的对象,再调用init方法对Applet自身进行初始化。
在init方法中可设置程序初始状态,载入图形或字体,获取HTML中<param>设定的参数等。案例1的Applet需要显示服务器上的图片文件,图片的下载可安排在init方法中进行。
2) publicvoidstart()
start方法在Applet启动时被调用。在整个Applet生命周期中,启动可发生多次。当Applet第一次被装入并初始化后,或者离开该页面后再次进入时,浏览器都会调用start方法。可以在start方法中通知Applet开始运行。
3) publicvoidstop()
stop方法用于停止执行Applet。在整个Applet生命周期中,停止执行可发生多次。当浏览器离开Applet所在Web页或关闭时,浏览器将调用stop方法。
stop方法挂起小程序,可在stop方法中释放系统资源,否则当浏览者离开一个页面时,小程序还将继续运行。
4) publicvoiddestroy()
destroy方法在Applet退出时被调用。在整个Applet生命周期中,退出只发生一次,即结束对该Web页的访问关闭Web浏览器时调用一次。
可在destroy方法中编写释放系统资源的代码,但除非用了特殊的资源(如创建的线程),否则一般不需重写destroy方法,因为Java运行系统本身会自动进行“垃圾”处理和内存
管理。
5) publicvoidpaint(Graphicsg)
paint方法负责绘制Applet的显示区域,可发生多次。当需要刷新Applet显示时,自动调用该方法。如果程序中修改了数据需要刷新显示,可用repaint方法强制系统调用paint方法重新绘制。
与前几个方法不同的是,paint中带有一个参数Graphicsg,它表明paint方法需要引用一个Graphics类的对象。在Applet中不用编程者操心,浏览器会自动创建Graphics对象并将其传送给paint方法,但应在Applet程序中引入Graphics类:
importjava.awt.Graphics;程序4.1演示了Applet的几个重要方法,该程序使用System.out输出部分信息,这部分信息在Applet中无法看到。使用appletviewer调试Applet时可以通过程序菜单打开Java显示控制台观察到这部分信息。下面是某次运行时的输出结果,读者可从中看出上面几个重要方法被调用的顺序:
Nowinit
Nowstart
Nowpaint
Nowpaint
Nowstop
Nowdestroy【程序4.1】Applet几个重要方法的调用顺序。
//AppletLife.java:
importjava.awt.*;
importjava.applet.Applet;
publicclassAppletLifeextendsApplet
{
publicvoidinit()
{
System.out.println("Nowinit");
}publicvoidstart()
{
System.out.println("Nowstart");
}
publicvoidstop()
{
System.out.println("Nowstop");
}
publicvoidpaint(Graphicsg)
{
System.out.println("Nowpaint"); g.drawString("hello",30,30);
}
publicvoiddestroy()
{
System.out.println("Nowdestroy");
}
}4.1.3图像文件的下载
java.awt.Graphics类提供了不少绘制图形的方法,但如果用它们在Applet运行过程中实时地绘制一幅较复杂的图形则并不容易。对于复杂图形,一般事先用专用的绘图软件绘制好,或者是用其他截取图像的工具(如扫描仪)获取图像的数据信息,按一定的格式存入图像文件。案例1要求显示两幅图像,Applet程序运行时,只需从指定位置将图像文件装载到内存里,然后在适当的时机将它显示出来。
Java目前所支持的图像文件格式有两种,分别是GIF和JPEG格式(带有 .GIF、.JPG、.JPEG后缀名的文件)。如果是其他格式的图像文件,可用图像处理软件先将它们转换为这两种格式。
Applet类提供了getImage方法,用以将准备好的图像文件装载到Applet中。该方法的参数指明了图像文件所存储的位置。由于Java语言是面向网络应用的,大部分情况是直接存取网络中Web服务器上的图像文件,因此Java采用URL(UniversalResourceLocation,统一资源定位器)来定位图像文件的网络位置,并定义URL类来管理URL信息(有关URL类的详细内容可参考本书第8章)。
getImage方法有两种调用格式:
ImagegetImage(URLurl)
ImagegetImage(URLurl,Stringname)第一种格式使用绝对URL形式,它指明了网络资源的全路径名,例如:
/java/imgsample/images/m1.gif
第二种格式使用相对URL形式,由基准URL(baseURL)再加上相对于基准URL下的相对URL两部分组成,例如上面的例子可表示为基准URL:
/java/imgsample/
与相对URL:
images/m1.gif
两部分。如果从当前Applet所在的网站装载图像文件,通常无需特意创建URL对象,可使用Applet类提供的两个方法来获取基准URL对象,然后给出图像文件的相对路径就可以了。这两个方法是:
URLgetDocumentBase()
URLgetCodeBase()
getDocumentBase()方法返回的基准URL对象代表了包含该Applet的HTML文件所处的目录,例如该文件存储在“/java/imgsample/m1.html”中,则该方法就返回“/java/imgsample/”路径。
getCodeBase()方法返回的基准URL对象代表了该Applet文件( .class文件)所处的目录。
getImage方法的返回值为Image对象,Java特别提供了java.awt.Image类来管理与图像文件有关的信息,执行与图像文件有关的操作应引入该类。
getImage方法将图像文件从网络上装入,交由Image对象管理。【程序4.2】案例1初步实现。
//下载图像文件
importjava.applet.*;
import.URL;
importjava.awt.Image;
publicclassshowPicextendsAppletimplementsjava.awt.event.MouseListener{
privateStringImageFile[]={“IMG_1.JPG”,“IMG_2.JPG”}; //图像文件名
privateImageAdImage[]=newImage[2]; //Image对象
publicvoidinit()
{
URLcodeBase=getCodeBase(); //获取基准URL
for(inti=0;i<2;i++)
AdImage[i]=getImage(codeBase,ImageFile[i]);
//从网站装载图像文件
}
}4.1.4图像的输出
Graphics类提供了drawImage方法将Image对象中的图像显示在特定位置上,调用格式如下:
booleandrawImage(Imageimg,intx,inty,ImageObserverobserver)
其中:img参数是要显示的Image对象;x和y参数是该图像左上角的坐标值;observer参数则是一个ImageObserver接口(interface)类型的对象,用来跟踪图像文件装载是否已经完成的情况,在Applet中可传递当前Applet对象的引用。除了将图像文件照原样输出以外,drawImage()方法的另一调用格式还能指定图像显示的区域大小:
booleandrawImage(Imageimg,intx,inty,intwidth,intheight,ImageObserverobserver)
这种格式多了两个参数width和height,分别表示图像显示的宽度和高度。若实际图像的宽度和高度与这两个参数值不一样,Java系统会自动将它进行缩放,以适合指定的矩形区域。为了不使图像因缩放而变形失真,可以将原图的宽和高均按相同的比例进行缩小或放大。原图的大小只需调用Image类中的两个方法就可以得到,它们的格式如下:
intgetWidth(ImageObserverobserver) //获取原图宽度
intgetHeight(ImageObserverobserver) //获取原图高度
同drawImage方法一样,通常用this作为observer的参数值。
程序4.3给出了案例1进一步的实现,运行该程序可以显示出第一幅图像。drawImage方法被调用时observer参数的实参为this,即当前的Applet。【程序4.3】案例1的改进。
importjava.applet.*;
importjava.awt.event.MouseEvent;
import.URL;
importjava.awt.Image;
importjava.awt.Graphics;
publicclassshowPicextendsApplet{
privateStringImageFile[]={"IMG_0277.JPG","IMG_0281.JPG"};
privateImageAdImage[]=newImage[2];privateintCurPic=0; //当前显示的图像编号
publicvoidinit()
{
URLcodeBase=getCodeBase();
for(inti=0;i<2;i++)
AdImage[i]=getImage(codeBase,ImageFile[i]);
}
publicvoidpaint(Graphicsg)
{
g.drawImage(AdImage[CurPic],0,0,this);
}
}4.1.5事件的响应
从前面的例子可以看出,JavaApplet小程序与Java应用程序在结构上有很大差异。Java应用程序有一个main方法顺序执行,当执行到输入数据的语句时,程序等待用户从键盘输入数据。用户输入数据后,程序继续执行,如果main方法执行结束,则程序终止运行。而JavaApplet似乎一直在执行,程序员无法知道用户什么时候按下鼠标按钮,不可能像应用程序那样等待用户的输入动作。
JavaApplet采用事件驱动的方法来接受用户的输入,事件表达了程序、系统及使用程序的用户之间的动作。JavaApplet启动运行后,超类中控制程序运行的代码会在适当的时候检测到用户的输入动作,根据动作的不同调用不同方法或由指定的对象来处理该事件。因此要响应鼠标按钮按下的动作,Applet需要做两件事:一是通知Applet当鼠标按钮按下后调用哪一个方法或由哪一个对象来处理,二是在该方法或指定对象的某个方法中实现所要完成的功能。
1.事件响应的一般方法
Java1.0 采用的方法比较简单,它预先在超类中指定了当发生某个事件时要调用的方法,只需在派生类中覆盖这些方法就可以实现事件的响应了。这种方法简单但缺乏灵活性,Java1.1以后的版本不再推荐使用,本书也不再赘述。
Java1.1及以后的版本中,事件处理采用委托模型,在程序中可以委托某一个对象处理特定的事件,该对象必须实现了指定的事件监听器接口。当Applet检测到某一个事件时,即通知该对象调用指定的方法来处理该事件。因此要处理某一事件至少需要完成下面两件事:
(1)定义一个类实现事件监听器接口。如果希望响应鼠标按下事件,则需实现MouseListener接口。
(2)登记事件监听器接口,即委托某个实现了监听器接口的类对象处理指定事件。例如响应鼠标事件可采用Applet类的addMouseListener方法:
addMouseListener(obj);
这里obj应是(1)中所定义类的对象。
当然,如果不再需要监听该事件,也可以移去事件监听器。移去事件监听器可采用Applet的removeMouseListener方法:
removeMouseListener(obj);这里的obj应与addMouseListener调用的参数为同一个对象。
不同类别的事件需要实现不同的事件接口,如果需要响应其他类型的事件,只需实现对应的接口,并使用对应的方法成员向事件监听器登记。Java1.1以后版本事件处理相关的类在包java.awt.event中,可使用import语句引入需要的类和接口:
importjava.awt.event.*;
2.鼠标事件的响应
鼠标事件处理模式实现的事件接口为MouseListener和MouseMotionListener。MouseListener主要响应鼠标的点击事件,包含5个方法成员,分别响应不同的鼠标事件:
publicvoidmousePressed(MouseEvente); //按下鼠标
publicvoidmouseReleased(MouseEvente); //鼠标按钮被释放
publicvoidmouseEntered(MouseEvente); //鼠标进入监听的组件
publicvoidmouseExited(MouseEvente); //鼠标离开监听的组件
publicvoidmouseClicked(MouseEvente); //鼠标单击
登记和移除MouseListener分别使用方法addMouseListener和removeMouseListener。
接口MouseMotionListener用于响应鼠标的移动事件:
publicvoidmouseDragged(MouseEvente); //鼠标拖动
publicvoidmouseMoved(MouseEvente); //鼠标移动
登记和移除MouseMotionListener分别使用方法addMouseMotionListener和removeMouseMotionListener。可以通过MouseEvent类中定义的方法getX、getY获取事件发生时鼠标的x、y坐标,或使用方法getPoint,该方法返回一个Point类型的对象。
程序4.4是案例1功能的完整实现,该例的Applet派生类showPic直接实现了MouseListner,因此在登记事件监听器时直接使用this参数,即当前Applet负责事件的处理,而无需另外创建对象。【程序4.4】案例1的实现。
importjava.applet.*;
importjava.awt.event.MouseEvent;
import.URL;
importjava.awt.Image;
importjava.awt.Graphics;
publicclassshowPicextendsAppletimplementsjava.awt.event.MouseListener{
privateStringImageFile[]={"IMG_1.JPG","IMG_2.JPG"};privateImageAdImage[]=newImage[2];
privateintCurPic=0;
publicvoidinit()
{
URLcodeBase=getCodeBase();
for(inti=0;i<2;i++)
AdImage[i]=getImage(codeBase,ImageFile[i]);
}
publicvoidstart()
{
addMouseListener(this);}
publicvoidstop()
{
removeMouseListener(this);
}
publicvoidpaint(Graphicsg)
{
g.drawImage(AdImage[CurPic],0,0,this);
}
publicvoidmouseClicked(MouseEvente){
CurPic=(CurPic+1)%2;repaint();
}
publicvoidmousePressed(MouseEvente){
}
publicvoidmouseReleased(MouseEvente){
}
publicvoidmouseEntered(MouseEvente){
}
publicvoidmouseExited(MouseEvente){
}
}
3.事件适配器
程序4.4中只响应鼠标单击事件,但是为了实现MouseListener接口必须实现5个方法,而MousePressed等4个方法对程序4.4来说没有实际意义。为了减少类似这种情况的不必要的代码,Java类库提供了事件适配器,使用内部类或匿名类配合事件适配器去监听事件,则仅仅需要重写要实现的方法即可。有关内部类及匿名类的详细语法这里不详细介绍,仅简单介绍如何使用匿名类实现事件的监听。
匿名类没有名字,只会使用一次。下面的代码创建一个匿名类对象,该匿名类派生自MouseMotionAdapter类,并覆盖了其mouseDragged方法。
newMouseMotionAdapter(){//匿名类开始
publicvoidmouseDragged(MouseEvente)
{
Strings=“Mousedragging:x=”+e.getX()+“Y”+e.getY();tf.setText(s);
}
}
这里的MouseMotionAdapter就是一个事件适配器,对应MouseMotionListener。java.awt.event包中定义的鼠标事件适配器还有MouseAdapter,对应MouseListener接口。程序4.5给出了使用事件适配器实现案例1的代码。
【程序4.5】使用事件适配器实现案例1。
importjava.applet.*;
importjava.awt.event.*;
import.URL;
importjava.awt.Image;
importjava.awt.Graphics;
publicclassshowPicextendsApplet{
privateStringImageFile[]={"computer.gif","forest1.gif"};privateImageAdImage[]=newImage[2];
privateintCurPic=0;
publicvoidinit()
{
URLcodeBase=getCodeBase();
for(inti=0;i<2;i++)
AdImage[i]=getImage(codeBase,ImageFile[i]);
//从网站装载图像文件
}
publicvoidstart(){
addMouseListener(newMouseAdapter()
{
publicvoidmouseClicked(MouseEvente){
CurPic=(CurPic+1)%2;
repaint();
}
}
);}
publicvoidpaint(Graphicsg)
{
g.drawImage(AdImage[CurPic],0,0,this);
}
}4.1.6在HTML中使用Applet
Applet使用appletviewer或Web浏览器加载运行,是通过HTML中定义的<APPLET>标记来实现的。第1章程序1.2中的HTML文件使用的是APPLET标记最简单的一种形式,APPLET标记更一般的形式如下:
<applet
codebase=codebaseURL
archive=archiveList
code=appletFile
alt=alternateText
name=appletInstanceName
width=pixelsheight=pixels
vspace=pixelshspace=pixels
align=alignment>
</applet>
APPLET标记本身不区分大小写,上面黑体字部分为APPLET标记必需的部分。下面介绍APPLET标记中属性的含义。● codebase属性:定义JavaApplet字节码文件的路径或地址(URL)。当Applet与HTML文档不在同一目录时用它来定位字节码文件,如果没有该属性,则表示Applet程序的字节码文件和HTML文档放在同一目录。
● code属性:指定调用的JavaApplet程序字节码文件名,要注意全名和大小写。
● archive属性:用逗号分隔的JAR文件列表。若Applet程序由多个类构成,可以将多个class文件打包生成JAR文件,以方便程序的发布。而且JAR文件采用zip压缩算法,可以减少class文件在网络上传输的数据量,加快下载速度。● width和height属性:指定Applet程序在Web浏览器中显示区域的宽度和高度,以像素为度量单位。
● vspace和hspace属性:用来设置以像素为单位的竖直和水平边距。
● align属性:控制Applet的对齐方式,取值为left、right、top、texttop、middle、absmiddle、baseline、bottom、absbottom。
● name属性:为Applet指定一个具体的名字,该名字在与同一页面的不同Applet通信时使用。
● alt属性:为不支持JavaApplet程序的Web浏览器显示替代的文字,如果支持则该属性被忽略。
APPLET标记可以在<applet></applet>之间使用<param>标记传递参数给Applet。例如:
<appletcode=“Java01.class”codebase=“javam”width=100height=60>
<paramname=“size”value=“5”>
<paramname=“font”value=“bold”>
</applet>
该APPLET标记定义了两个参数,参数名分别为size与font,两个参数的值分别为5和bold。Applet类提供了方法getParameter以获取参数的值。getParameter方法的形式为
publicStringgetParameter(String
name)其中形式参数name用于指定传递给Applet的参数名。
下面是VisualJ++6.0生成的Applet程序框架中获取参数的程序片段,请读者注意其中的黑体字部分:
private finalStringlabelParam=“label”;
private finalStringbackgroundParam=“background”;
private finalStringforegroundParam=“foreground”;
//此处省略多行
StringlabelValue;
StringbackgroundValue;
StringforegroundValue;labelValue=getParameter(labelParam);
backgroundValue=getParameter(backgroundParam);
foregroundValue=getParameter(foregroundParam);
对应的HTML文件中APPLET标记如下:
<applet code=Applet1.classname=Applet1 width=320height=200>
<paramname=labelvalue="ThisstringwaspassedfromtheHTMLhost.">
<paramname=backgroundvalue="008080">
<paramname=foregroundvalue="FFFFFF">
</applet> 4.2图形输出
4.2.1案例2:鼠标绘图程序
案例1实现了图像文件的显示,但有时需要实时绘制图形,而不是输出预先准备好的图像。本节我们实现一个简单的鼠标绘图程序。图4.3是该程序在JBuilder下运行的画面,按下鼠标并拖动时开始画线,释放鼠标按键时停止,再次拖动鼠标时重新开始画线。图4.3鼠标绘图程序的运行画面4.2.2Java的图形坐标系统
为了将某一图形在屏幕上绘制出来,首先要确定图形的位置,为了解决这个问题就必须有一个精确的图形坐标系统来定位图形。
与大多数其他计算机图形系统所采用的二维坐标系统一样,Java语言的图形系统的坐标原点(0,0)在屏幕的左上角,水平向右为X轴的正方向,竖直向下为Y轴的正方向。每个坐标点的值表示屏幕上的一个像素点的位置,因此,所有坐标点的值都取整数。图4.4表示用此图形坐标系统在屏幕上绘制一个矩形。图4.4Java的图形坐标系统4.2.3案例2的实现
Graphics类提供了丰富的绘图方法(method),利用Graphics类可以绘制各种图形和文本。案例2要求随着鼠标移动的轨迹绘制图形,实际上只需要当鼠标拖动时取出其坐标位置,用直线连接起来就可以了。
Graphics类中提供画线功能的是drawLine()方法,其调用格式如下:
drawLine(intx1,inty1,intx2,inty2)该方法需要设置四个参数,其中x1,y1表示线段的一个坐标点,x2,y2表示线段的另一个坐标点。Graphics类不专门提供画点的方法,如果要画点则用drawLine将两点坐标设为相同即可。
结合画线的方法和前面关于鼠标事件响应的方法,案例2的功能实现代码见程序4.6。【程序4.6】鼠标画线程序。
importjava.awt.*;
importjava.applet.*;
importjava.awt.event.*;
publicclassDrawLineextendsAppletimplementsMouseListener,
MouseMotionListener
{
PointstartPoint;
Pointpoints[]; intnumPoints=0;
booleandrawing=false;
publicvoidinit()
{
startPoint=newPoint(0,0);
points=newPoint[1000];
}
publicvoidstart()
{
addMouseMotionListener(this); //this作参数 addMouseListener(this);
}
publicvoidpaint(Graphicsg)
{
for(inti=0;i<numPoints-1;i++){
g.drawLine(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
}
}
publicvoidstop() {
removeMouseMotionListener(this);
removeMouseListener(this);
}
publicvoidmouseDragged(MouseEvente)
{
if(drawing&&numPoints<1000){
points[numPoints]=newPoint(e.getX(),e.getY());
numPoints++;
repaint(); }
}
publicvoidmouseMoved(MouseEvente){}
publicvoidmousePressed(MouseEvente)
{
drawing=true;
numPoints=0;
}
publicvoidmouseReleased(MouseEvente)
{
drawing=false; }
publicvoidmouseEntered(MouseEvente){}
publicvoidmouseExited(MouseEvente){}
publicvoidmouseClicked(MouseEvente){}
}
4.2.4其他常见图形的绘制方法
除了直线,Graphics类还提供了直接绘制常见几何图形的方法。
1.绘制矩形
Graphics类提供了三种类型的矩形,分别为普通矩形、圆角矩形和立体矩形。每一种矩形都提供两种不同风格的方法:一种是仅画出矩形的边框;另一种是不仅画出边框,还用相同的颜色填充整个矩形区域。
绘制普通矩形调用drawRect或fillRect方法,格式如下:
drawRect(intx,inty,intwidth,intheight) //边框型风格
fillRect(intx,inty,intwidth,intheight) //填充型风格其中前两个参数表示矩形左上角的x坐标和y坐标,后两个参数分别表示矩形的宽度和高度。
圆角矩形的四个顶角呈圆弧状,每个圆弧都是由1/4的椭圆弧所构成的。画圆角矩形的两个方法的调用格式如下:
drawRoundRect(intx,inty,intwidth,intheight,intarcWidth,intarcHeight)
fillRoundRect(intx,inty,intwidth,intheight,intarcWidth,intarcHeight)
其中前四个参数与普通矩形含义相同,第五个参数arcWidth代表了圆角弧的横向直径,第六个参数arcHeight代表了圆角弧的纵向直径。
Java中的立体矩形其实并非真正的三维图形,只是在矩形的边框上增加了一点阴影,使矩形看上去相对平面好像有凸出或凹下的效果。绘制方法为
draw3DRect(intx,inty,intwidth,intheight,booleanraised)
fill3DRect(intx,inty,intwidth,intheight,booleanraised)
这两个方法中的前四个参数与drawRect方法中所用的参数含义是一样的,第五个参数raised定义该立体矩形是具有凸出(值为true)还是凹下(值为false)的效果。
2.绘制多边形
多边形的绘制方法通常是给出一组坐标点,再用直线段将这些点依次连接起来。Graphics类中提供两个方法来画多边形,一个是边框型drawPolygon方法,另一个是填充型fillPolygon方法,每一种方法都有两种不同的参数类型。
第一种参数类型的调用格式为
drawPolygon(intxPoints[],intyPoints[],intnPoints)
fillPolygon(intxPoints[],intyPoints[],intnPoints)
其中xPoints参数是一个整数数组,用以存放多边形坐标点的X坐标值;yPoints参数存放相应的一组Y坐标值;nPoints则表示共有几个坐标点。例如,下面的paint方法分别画了一个边框型和一个填充型的多边形。publicvoidpaint(Graphicsg){
intPoly1_x[]={30,63,115,72,67};
intPoly1_y[]={40,20,95,74,106};
intPoly1_pts=Poly1_x.length;
intPoly2_x[]={180,213,265,222,217};
intPoly2_y[]={40,20,95,74,106};
intPoly2_pts=Poly2_x.length;
g.drawPolygon(Poly1_x,Poly1_y,Poly1_pts);
g.fillPolygon(Poly2_x,Poly2_y,Poly2_pts);
}第二种参数类型的调用格式为
drawPolygon(Polygonp)
fillPolygon(Polygonp)
其中Polygon是定义在java.awt中的一个类,它的构造方法有两种不同的参数传递形式。一种与drawPolygon()方法的第一种调用格式一样:
Polygon(intxPoints[],intyPoints[],intnPoints)
另一种调用格式则是使用无参数构造方法创建一个空的多边形,再用addPoint()方法将多边形的坐标点动态地增加到Polygon对象中。
3.绘制椭圆和圆
绘制椭圆的方法是给出该椭圆的外接矩形作为参数,其调用格式与画普通矩形的方法相似:
drawOval(intx,inty,intwidth,intheight) //边框型风格
fillOval(intx,inty,intwidth,intheight) //填充型风格
特别要注意x和y不是椭圆的圆心坐标,而是该椭圆外接矩形的左上角。因此,画椭圆时,把它先看做是一个矩形将有助于在坐标系统中定位。
Graphics类不专门提供画圆的方法,只要在绘制椭圆时将width与height参数置成相等就可以了。下面的paint方法绘制了一个圆和一个用颜色填充的椭圆。
publicvoidpaint(Graphicsg){
g.drawOval(30,20,60,60);
g.fillOval(130,20,80,60);
}
4.画弧
弧是椭圆的一部分,画弧的方法就相当于先画一个椭圆,而后取该椭圆中所需要的一部分。它们的调用格式如下: drawArc(intx,inty,intwidth,intheight,intstartAngle,intarcAngle) //边框型风格
fillArc(intx,inty,intwidth,intheight,intstartAngle,intarcAngle) //填充型风格
其中前四个参数的含义与画椭圆一样;后两个参数即用来定义椭圆的一部分,startAngle参数表示该弧从什么角度开始,arcAngle参数表示从startAngle开始转了多少度。水平向右表示0°,逆时针方向为正角度值,顺时针方向为负角度值。如果startAngle和arcAngle中有任一值大于360°,都会被转换为0~360°之间的数值。另外,fillArc()方法的效果并不是填充弧的两个端点直接连线所围的区域,而是填充弧的两端点与圆心连线所围的扇形区域,像一个饼图。
5.复制与清除图形
当需要重复绘制一些相同的图形时,也可采用Graphics类中的copyArea方法,它能将屏幕上某一矩形区域里的内容复制到屏幕的另一区域。其调用格式如下:
copyArea(intx,inty,intwidth,intheight,intdx,intdy)其中前四个参数定义了要被复制的屏幕的矩形区域;最后两个参数则表示新区域与原始屏幕区域的偏移距离:若dx,dy为正值,则表示新区域相对于原区域的右方及下方所偏移的像素值,反之则分别表示相对左方及上方的偏移量。
若要清除屏幕的某一矩形区域所画的内容,可用clearRect方法,它用当前的背景颜色来填充整个矩形区域。其调用格式为
clearRect(intx,inty,intwidth,intheight)其中四个参数定义了所要清除的矩形区域。例如,想要清除整个Applet区域,可先调用Applet类的size()方法得到整个Applet的宽度和高度(该方法没有参数,返回值是一个Dimension对象),再调用clearRect()方法就可以了。例如:
g.clearRect(0,0,size().width,size().height);
4.2.5文本的输出
程序1.2调用Graphics类的drawString方法在屏幕上显示一个字符串,没有指定字体和颜色,drawString使用缺省的字体和颜色输出,输出结果显得很一般。如果希望输出的文本显示更具特色,可以指定某种字体、某种风格、尺寸大小和色彩。
1.字体的设置
如果程序需要在屏幕上输出文本信息,首先要确定采用何种字体,例如中文的“宋体”、“楷体”,或英文的“TimesRoman”体、“Courier”体等;接着再决定该字体输出时采用哪种风格,是斜体还是粗体等;最后还要确定该字体的大小尺寸。所有这些都由Font类来定义,其构造方法的形式为
publicFont(Stringname,intstyle,intsize)
它的三个参数分别代表字体名、字体风格和尺寸大小。
name指定文本输出的字体,如果运行该Applet的客户端系统未安装该字体,Java会以缺省字体来替代它。客户端系统支持的字体可以用java.awt.Toolkit类中的getFontlist()方法来获得,它返回系统目前可用的字体列表,然后就可决定到底选用哪种字体。例如:
Toolkitsystk=Toolkit.getDefaultToolkit();
String[]fonts=systk.getFontList();
Font类中已定义了静态常量来表示字体的style值,如Font.BOLD(粗体)、Font.ITALIC(斜体)、Font.PLAIN(普通体),可以进行相加运算来生成复合style。例如,想让style既是粗体又是斜体,可以这样写:
Fontfn=newFont(“TimesRoman”,Font.BOLD+Font.ITALIC,28);
创建了Font对象以后,用Graphics类的setFont()方法即可将所创建的Font对象设为当前所用的字体。setFont的形式为
publicvoidsetFont(Font
font)
设置字体后可以利用Graphics类中提供的drawString()、drawChars()等方法来输出字符串与字符,形式如下:
publicvoiddrawString(String
str,int
x,int
y)
publicvoiddrawChars(char[]
data,int
offset,int
length,int
x,int
y)
drawString方法中的参数str为要显示的字符串;x,y指明字符串显示的起始位置坐标,其中x表示第一个字符的左边界,y表示整个字符串的基线(baseline,见图4.5)位置。
drawChars方法则是用来显示多个字符的,从给定的字符数组中抽取连续的一部分显示在屏幕上。其中data参数就是给定的字符数组,offset表示从第几个字符位置开始,length表示共显示几个字符,x与y参数的含义与drawString方法一样。图4.5字符串输出的坐标示意图程序4.7显示了一些不同的文本字体,其显示结果如图4.6所示。
【程序4.7】用指定的字体输出文本。
importjava.awt.Graphics;
importjava.awt.Font;
publicclassFontDemoextendsjava.applet.Applet{
publicvoidpaint(Graphicsg){
Fontftp20=newFont("TimesRoman",Font.PLAIN,20);
Fontfai15=newFont("Arial",Font.ITALIC,15);
Fontfcb24=newFont("Courier",Font.BOLD,24); Fontfsib30=newFont("宋体",Font.ITALIC+Font.BOLD,30);
g.setFont(ftp20);
g.drawString("FontnameTimesRoman,styleplain,size20",10,20);
g.setFont(fai15);
g.drawString("FontnameArial,styleitalic,size15",10,50);
g.setFont(fcb24);
g.drawString("FontnameCourier,stylebold,size24",10,80); g.setFont(fsib30);
g.drawString(“字体名宋体,风格斜体+粗体,尺寸30”,10,120);
}
}
系统当前所用的字体信息可以用Graphics类中的getFont()方法获得,该方法无参数,它返回系统当前所用的Font对象,然后就可以调用Font类中提供的几个方法来获取该字体的基本信息。表4.1列出了Font类中的这些方法,表中只给出了方法名。图4.6程序4.7的输出结果表4.1Font类提供的一些主要方法
2.颜色的设置
与设置字体信息相似,要设置新的颜色,必须先创建Color对象,然后再调用Graphics类中设置颜色的方法来将该Color对象设为当前所用的绘图颜色。
Java中每一种颜色都看成是由红(R)、绿(G)、蓝(B)三原色组合而成的,因此Color类的构造方法形式如下:
Color(intr,intg,intb)其中每个参数的值都在0~255之间,数值越大就表明这种颜色的成分越重。例如(0,0,0)代表黑色,(255,0,0)代表红色。若客户端系统不支持当前所定义的颜色值,Java会挑选最接近的颜色来代替。
Color类中定义了一些标准颜色的Color对象,使得这些标准颜色的引用显得更为方便。这些类变量如表4.2所示。表4.2标准的Color对象创建Color对象后,还需调用Graphics类中的setColor方法把这个对象设置为系统当前所用的绘画颜色,调用格式为
setColor(Colorc)
例如,想要用蓝色来显示文本,最简单的办法是直接引用标准色的类变量:
setColor(Color.blue);
另外,Java还提供了设置整个Applet的背景和前景的方法,它们分别是setBackground和setForeground方法。它们都被定义在java.awt.Component类中,因此该方法能被其子类(包括Applet类及Applet类的子类)继承,它们的调用格式与setColor()方法一样:
setBackground(Colorc)
setForeground(Colorc)
其中,setForeground()方法将影响到Applet中所有已经用其他任何颜色所绘制的图形及显示的文本,可把它们全都变为该方法所定义的前景色,而无需重新一一绘制。
与字体类似,Java也提供了getColor方法(Graphics类中)、getBackground方法和getForeground方法(Component类中)来分别获取当前的绘图颜色、Applet背景及前景颜色的对象。
程序4.8显示了若干行用随机定义的颜色输出的文本。【程序4.8】用指定的颜色输出文本。
importjava.awt.Graphics;
importjava.awt.Color;
publicclassColorDemoextendsjava.applet.Applet{
publicvoidpaint(Graphicsg){
intred,green,blue;
for(inti=10;i<200;i+=15){
red=(int)Math.floor(Math.random()*256);
green=(int)Math.floor(Math.random()*256);
blue=(int)Math.floor(Math.random()*256);
g.setColor(newColor(red,green,blue));
g.drawString("Color",1,i);
}
}
}
4.3图形用户界面设计
4.3.1案例3:图形界面的简易计算器
案例1和案例2实现了图像的输出和图形的绘制,但通常我们在Windows操作系统下看到的很多应用程序窗口,它们是由一些固定的界面元素如按钮、编辑框、标签等构成的,利用案例1和案例2的方法来绘制图形界面的这些元素不但费时而且也没有必要。Java.awt包中已经提供了这些界面元素的实现,将它们的实现封装为一些类,程序员可以很容易利用这些类来构造复杂的用户界面。本节案例要求实现一个图形界面的简易计算器,其运行界面如图4.7所示。该计算器能够进行加减乘除运算,点击“CLEAR”按钮计算器值清零。图4.7简易计算器4.3.2容器与组件
Java类库中与图形界面有关的基本类都放在java.awt包中。AWT是Java语言提供的用户界面设计工具,它是抽象窗口工具包(AbstractWindowingToolkit)的英文缩写。由于Java是一个跨平台的编程语言,AWT并不试图实现任何特定的图形界面操作系统的所有特征,它仅仅实现所有操作系统的普通特征,以保证其跨平台的特性。
AWT中将构成用户界面的各种元素如按钮、标签等称为组件,组件的共同特征由Component类实现,其他大多数组件都是由Component类派生而来的。正如我们在Windows环境下看到的,按钮一类的界面元素并不是独立存在的,它们都是放置在某个窗口、面板等上的。AWT将这些窗口和面板称为容器,容器类也是从Component类派生而来的,它们是一类特别的组件,可以在容器上放置其他组件。对于案例3来说,Applet就是一个容器,可以在上面放置按钮、标签等组件。按钮、标签这一类的组件是一般的组件,不能像容器那样放置其他组件。
容器用来组织其他界面元素,一个应用程序的图形界面首先对应于一个复杂的容器,如一个窗口。这个容器内部将包含许多界面元素,这些界面元素本身又可以是一个容器,这个容器将再进一步包含其他的界面元素,构成一个复杂的图形界面系统。常见的容器组件有Applet、Panel、Window、Frame、Dialog等。容器组件提供了方法add用来将组件对象加入到容器中。例如将下面的代码放入Applet的init方法,则建立一个按钮并加入到Applet中。
Buttonbutton1=newButton(“Hello”); //创建组件对象
add(Button1); //将组件加入容器
这里Button为命令按钮组件的类名,以按钮上的提示文字作为构造方法的参数。命令按钮是图形界面中非常重要的一种基本组件,当用户点击按钮时,系统自动执行与该按钮相联系的程序,从而完成预先指定的功能。
Button类有两种构造方法:
● publicButton();——构造一个没有提示文字的按钮;
● publicButton(Strings);——构造一个以给定字符串为提示文字的按钮。
例如,下面的语句定义一个“OK”按钮:
Buttonb=newButton(“OK”);
Button组件提供了一些方法获取和设置某些属性。例如,获得按钮上的提示文字可以使用:
publicStringgetLabel();改变按钮上的提示文字可以使用:
publicvoidsetLabel(Strings);
案例3界面上需要的另一个组件是标签,标签是最简单的组件,其实质就是一段文字。Label类中定义了三种构造方法:
● publicLabel();——构造一个空的标签,不显示任何内容;
● publicLabel(Stringtext);——构造建立一个以String为内容的标签;
● publicLabel(Stringtext,intalignment);——定义一个标签。参数alignment代表一个给定的对齐方式,可以是靠左、靠右和居中,缺省设置是靠左。Label类中定义了相应的常量Label.LEFT、Label.RIGHT和Label.CENTER来表示这三种对齐方式。下面的语句定义一个居中的Name标签:
Labell1=newLabel(“Name”,Label.CENTER);
Label类还定义了一些方法来获取或修改标签对象的设置:
● publicStringgetText();——获得标签上的文字;
● publicvoidsetText(Stringtext);——修改标签上的文字;
● publicintgetAlignment();——获得标签的对齐方式;
● publicvoidsetAlignment(intalignment);——设置标签的对齐方式。
现在可以将案例3界面所要求的按钮和标签加到Applet上,程序4.9给出了源代码。【程序4.9】案例3界面的初步构造。
importjava.awt.*;
publicclassAppletCalextendsjava.applet.Applet{
Labeltitle=newLabel("简易计算器",Label.CENTER);
LabelDisplayStr=newLabel("0",Label.RIGHT);
Buttonbuttons[]=newButton[17];
StringbuttonStr[]=
{"7","8","9","+","4","5","6","-","1","2","3","*","0",".","=","/","CLEAR"};publicvoidinit()
{
add(title); //第一行为标题
add(DisplayStr); //第二行为计算器显示区
intj=0;
for(inti=0;i<16;i++){ //前16个按钮,每行4个
buttons[i]=newButton(buttonStr[i]);
add(buttons[i]);
}
//最后一行为“CLEAR”、“关于”按钮
buttons[16]=newButton(buttonStr[16]);
add(buttons[16]);
}
}
4.3.3组件的布局
运行程序4.9可以发现,虽然标签和按钮组件都已加入到Applet上去了,但界面并不符合要求,所有的组件对象都挤在上面两行,如图4.9所示。图4.8程序4.9运行界面再观察一下程序4.8的代码,可以发现,组件是按顺序加入Applet的,但是并没有指定这些组件如何在Applet上布局,放置在什么位置。图4.8中的位置是怎么决定的呢?实际上这是由Applet的默认布局管理器布置的。
布局管理器用于控制组件在容器中的位置。由于Java的跨平台特性,使用AWT编制图形界面的程序一般不采用绝对位置定位组件。如果采用绝对位置定位组件,可能会使图形界面在不同平台下差异较大,例如一个相同的按钮组件在Windows平台中的高度为25像素,但在Motif平台上显示时却是28像素,这样在Windows平台上运行良好的用户界面在Motif平台上可能会相互挤成一团。布局管理器只允许声明组件间的相对位置和前后关系,无需指定组件的大小,这样布局管理器就可以自动调整组件显示,从而达到界面的平台无关性。
AWT提供五种布局管理器供选择:FlowLayout、GridLayout、GridBagLayout、BorderLayout和CardLayout。用户可以使用类似下面的语句来选择布局管理器:
publicvoidinit(){
setLayout(newFlowLayout());
}
下面逐一介绍这五种布局管理器。
1.FlowLayout
FlowLayout是最简单的布局管理器,也是AWT采用的缺省布局方式。它的布局原则是将组件从左向右、从上向下排列,如果这行放不下这个组件,就放入下一行。
FlowLayout可设置布局的对齐方式为居中、靠左或靠右,缺省对齐方式为居中。可以在创建FlowLayout对象时使用该类中定义的常量CENTER、LEFT和RIGHT指定对齐方式。例如:
setLayout(newFlowLayout(FlowLayout.LEFT);
另外,FlowLayout还可以设置组件间横向和纵向的间隔,缺省是5个像素。下面的语句将横向间隔设置为5个像素,纵向间隔设置为10个像素。
setLayout(newFlowLayout(FlowLayout.CENTER,5,10);
2.GridLayout
GridLayout布局管理器将容器划分成网格状,每一个组件按照添加的顺序从左向右、从上向下地占据一个单元。在GridLayout中,组件添加的顺序相当重要。程序4.10采用2×3的网格布局,图4.9是执行的结果。图4.9GridLayout布局演示【程序4.10】GridLayout布局管理器。
importjava.awt.*;
importjava.applet.*;
publicclassApplet1extendsApplet
{
publicvoidinit()
{
setLayout(newGridLayout(2,3,20,35));
add(newButton("Button1"));
add(newButton(“Button2”));
add(newButton(“Button3”));
add(newButton(“Button4”));
add(newButton(“Button5”));
add(newButton(“Button6”));
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年医用高频仪器设备项目提案报告模范
- 生命小学作文15篇
- 2024-2025学年许昌市魏都区三年级数学第一学期期末综合测试试题含解析
- 2024-2025学年新源县三上数学期末检测试题含解析
- 2025年水用电磁阀项目立项申请报告模范
- 个人辞职报告19篇
- 个人年终总结合集15篇
- 2024年校园护卫人员标准聘用合同模板版B版
- 员工离职证明书(15篇)
- 2023行政主管年终工作报告五篇
- 儿童版画(版画基础)
- 现代奶牛饲养技术考试考核试卷
- 车辆提档委托书样本
- 充值消费返利合同范本
- 2024上海市地方标准住宅电梯安全管理规范
- GB/T 18488-2024电动汽车用驱动电机系统
- 2023-2024学年成都市武侯区九年级上英语(一诊)期末考试题(含答案)
- DZ∕T 0130-2006 地质矿产实验室测试质量管理规范(正式版)
- 2024年高中语文选择性必修下册理解性默写含答案
- 2023北师大版新教材高中数学选择性必修第一册同步练习-全书综合测评
- 《小学五年级期末家长会》课件模板(五套)
评论
0/150
提交评论