学了几天Java,就迫不及待地想进入图形界面,因为图形界面可以给人一个直观的视觉效应,如果自己在记事本中写的一行行枯燥的代码可以变成美丽的图形,那该是一种什么感受啊!下面我将会分步骤讲解一个画图程序,供大家参考。
首先构思一个画图程序的界面
假设这个程序的界面如上所示,文件菜单中有清屏、打印和退出功能,这个程序的主要功能就是可以完成画图的功能,如图所示,可以画红色、绿色、蓝色、黑色的图形,可选的图形先假设有矩形和椭圆形,Filled的功能为是否填充封闭图象。
在开始创建图形界面前,先介绍一下创建图形的基本知识。
Frame,也叫框架,它是由一个包括最大化、最小化、关闭和Frame名称所组成的一个框架运行界面。Panel,也叫面板,将Panel添加在Frame上可以使得许多事情变得容易解决,这一点我们将在后面看到,如下,是一个将100×100的Panel添加到200×200的Frame上的界面,注意,为什么Panel显示的是一个矩形框?这是由于原点选取的是包括标题行最左上角的(0,0)。
Frame的默认布局管理器为边界布局管理器,Panel的默认布局管理器为流式布局管理器,所谓的布局管理器分为好多种,最常见的有流式布局管理器(FlowLayout)、边界布局管理器(BorderLayout)和表格布局管理器(GridLayout)。
1.流式布局管理器是将组件流水似的摆放在Frame或其它构件上,从左到右,依次排放,遇到边界就重新另起行,顺序排放,整体置放在中央的位置。如下所示(这是将Button添加到Frame上,由于Frame的默认布局管理器不是FlowLayout,所以要进行相应的修改,修改方法将在后面介绍):
将Frame拉大的时候上图5个Button将顺序摆放在Frame中部,排成一行,而将Frame缩小的时候,将显示成下图的状态:
五个Button始终还是顺序排放的,只不过在一行中摆放不下的时候将换行排放。
2.边界布局管理器则将板块分为东西南北中五个方向,每添加一个组件就要指定组件摆放的方位,放置在东西南北四个方向的组件将贴边放置,如下所示:
当拉大Frame的时候,处在center(中间)的组件就不断积压东西南北四个方向的组件,如下图所示,Button4和Button3只是拉长而宽度不变,而Button1和Button2只是拉宽,而长度不变,Button5则是长宽都变化:
3.表格布局管理器就是分几行几列将部件摆放到Frame上去,几个部件也是贴边放置的,如下图所示,将6个Button按2行3列排放:
将Frame拉大了的结果如下
上面提到了关于修改布局管理器的问题,Frame的默认布局管理器是边界布局管理器,如果要将它转化成FlowLayout或者GridLayout甚至null的布局管理方式应该如何处理呢?java给我们提供了修改的方法,假设创建的Frame对象为f,那么将其修改成FlowLayout的方法就是f.setLayout(new FlowLayout()),而如果修改成null,则只需要写成f.setLayout(null)即可。
有了以上的知识,我们就可以开始进行我们的图形创作了,
首先要添加一个MenuBar,也就是菜单项,虽然Frame是默认BorderLayout的,但是也没有必要将MenuBar放置在最上面,因为MenuBar默认就是一定要放在最上方的,即使是再添加一个置于NORTH的部件,也是位于MenuBar下方的。
中间我们留出的主要部分是画图用的,需要较大的空间,所以放置在CENTER部位。
下方的部件比较多,也比较复杂。选择图形类型的部件叫做Choice,单选框和复选框都叫做Checkbox,不同的地方是,对于单选框而言,要添加一个叫CheckboxGroup的部件将单选框圈在其范围内,这样我们就可以完成单选的功能了。于是,需要放在最下方的部件有3个之多,那么,如果都使用BorderLayout.SOUTH的话,几个部件将叠加在一起,我们就只能够看见最上方的部件,这样的结果显然不是我们希望的。那么怎么处理这个问题呢?我们知道Panel的默认布局管理器是FlowLayout的,那么如果我们将一个Panel加在Frame的最南端,然后依次加入Choice和Checkbox单选框和复选框,那么问题就可以解决。
现在,让我们来着手做我们自己的图形界面吧!
首先要引入java.awt.*,这个包是基本的图形包,如Frame,Panel都在这个包中。引用方法为:import java.awt.*;
接下来你可以创建一个叫做Drawing的类,让它继承原包中有的Frame类,在Drawing类中,可以添加自己想要的功能以完善这个Frame,继承用extends来操纵,如下:
public class Drawing extends Frame
{
Drawing(String ss)
{
setTitle(ss); //设置标题
setVisible( true );
}
public static void main(String args[])
{
Drawing d = new Drawing("Paint Program");
}
}
在main函数中创建了一个Drawing的对象,命名为d,并传递这个Frame的标题名,类Drawing中的Drawing(String ss)表示对Drawing重新构造了一遍,Drawing(String ss)称为过载,ss接受main函数传递过来的字符串。如果不使用过载方式也可以完成,程序如下修改即可:
public class Drawing extends Frame
{
Drawing()
{
setTitle("Paint Program");
setVisible( true );
}
public static void main(String args[])
{
Drawing d = new Drawing();
}
}
由于Drawing继承了Frame,所以Drawing本身也是一个Frame,所以它可以设置标题(setTitle(ss)),可以添加组件。现在程序就已经可以运行了,但只会是一块白板,什么都没有,大家有兴趣的话可以试一下。记住,setVisible(true)这句话不可省略,如果省略,就什么都看不见了。
如果按照上面尝试运行了一下,你就会发现这个程序还是有很多弊病的,例如图象没有立刻显现出来,要将Frame拉开(或者点最大化)才可以看得见那块白板,更要命的就是程序无法关闭,因为对关闭程序内容我们并没有做任何处理,你需要到任务管理器中找到一个叫javaw.exe或java.exe的线程,将它关闭才可以,这给我们带来了很多的麻烦,那么怎么解决这些问题呢?首先,我们可以设置Frame的大小,并且还可以将它设置为不可修改大小的,添加如下两条语句即可:
setSize (400,400); //设置大小
setResizable( false ); //将大小改为不可更改的
那么如何完成关闭程序的功能呢?我们需要调用一个系统的监听,如下添加:
addWindowListener( new WindowAdapter(){
public void windowClosing( WindowEvent e ){
System.exit( 0 );
}
});//增加关闭程序功能
这样调用的一个Frame的addWindowListener方法进行关闭处理,就可以满足我们的需求了,这个方法是系统提供的,完成的就是关闭程序的功能。
下面,我将讲解将如何描述MenuDown、MenuUp和Draw类。因为这三个类都是放置在刚才我们创建的Drawing上的,为了方便调用,我们可以将这三个类放置在Drawing类中,这叫做内部类。下面,我们先创建一个菜单类—MenuUp:
class MenuUp extends MenuBar
{
public MenuUp(){
Menu m1 = new Menu( "File" );
Menu m2 = new Menu( "Help" ); //创建两个菜单目录项
MenuItem mi1 = new MenuItem( "Clear" );
MenuItem mi2 = new MenuItem( "Print" );
MenuItem mi3 = new MenuItem( "Quit" ); //创建3个菜单项
m1.add( mi1 );
m1.add( mi2 );
m1.addSeparator();
m1.add( mi3 ); //将3个菜单项添加到名为File的菜单下,并加分隔符
add( m1 );
add( m2 );
setHelpMenu( m2 ); //将菜单目录项添加到MenuBar中
}
}
首先,类MenuUp继承了MenuBar类的性质,所谓的MenuBar就是类库中已经创建好的可供继承和使用的类,它的默认放置是在面板中的最上端,可以为它添加菜单项,这个可以由用户自行编写,如上,我们创建了两个菜单目录项,即File和Help,注意,由于Help是一个特殊的菜单,一般放置在菜单栏的最末位,所以添加的时候也需要注意,要添加一条setHelpMenu()的语句。程序中的“对象.add()”表示在对象中添置一些其它的对象,“对象.addSeparator()”是指添加分隔符的意思。
创建好这个类后,在Drawing(String ss)中要添加一条setMenuBar( new