资源描述
,第二级,第三级,第四级,第五级,第8章 Java的GUI设计,第8章 Java的GUI设计,8.1 AWT基础,8.2 窗口类,8.3 AWT基本组件,8.4 菜单,8.5 布局管理器,8.6 Java AWT事件处理机制,8.7 Swing基础,8.1 AWT 基 础,开发图形界面的应用程序时,需要用到AWT(抽象图形工具集)。AWT是Java开发工具包(JDK)的一部分,是Java基本类(JFC)的核心。AWT的作用是给用户提供基本的界面组件,如:窗口、按键、菜单等。此外,AWT还提供事件处理结构,支持剪贴板、数据传输和图像操作。,在Java 1.0中,AWT最初的设计目标是提供一个用来建立图形用户界面的独立平台,可以让程序员组建一个通用的GUI,使其在所有平台上都能正常显示。遗憾的是,这个目标并没有很好的实现,但幸运的是,这种情况从Java 1.1以后得到了大的改进。从Java 1.2开始,AWT添加了被称为“Swing”的新GUI库。,Swing是基于AWT基本结构创建的二级用户界面工具集。与旧的AWT相比,Swing提供更加丰富的组件集,Swing中所提供的组件集几乎可以替代所有AWT中原有的组件。由此,许多人也许会产生Swing是AWT的替代物的误解,而实际上Swing是基于AWT之上创建的。因此,为了准确的掌握Swing组件集的工作方式,必须首先掌握AWT组件的行为及其工作原理。,8.1.1 java.awt包简介,AWT在java.awt包中提供,表8.1列出了AWT中的Java软件包。,AWT包含四个主要的类:组件类(Component)、容器类(Container)、图形类(Graphics)和布局管理器类(LayoutManager和LayoutManager2)。, Component(组件)类 菜单、按键、列表等组件的抽象基本类。, Container(容器)类 扩展Component的抽象基本类。由Container派生的类有Panel、Applet、Window、Dialog和Frame类等。在容器中,可以包含多个组件。, Graphics(图形类)类 定义组件内图形操作的基本类。每个组件都有一个相关的图形对象。, LayoutManager(布局管理器)类 定义容器中组件的位置和尺寸的接口。Java中定义了几种默认的布局管理器。,表8.1 AWT中的软件包,软 件 包,描 述,java.awt,基本组件实用工具,java.awt.accessibility,辅助技术,java.awt.color,颜色和颜色空间,java.awt.datatransfer,支持剪贴板和数据传输,java.awt.dnd,支持拖放,java.awt.event,事件类和监听器,java.awt.font,2D API字体软件包,java.awt.geom.,2D API几何软件包,java.awt.im,引入方法,java.awt.image,图像处理工具包,java.awt.peer,同位体组件、界面包,java.awt.print,支持打印2D API,java.awt.swing,Swing组件,java.awt.test,测试AWT方法有限子集的独立applet,组件、容器和布局管理器构成了AWT中的简单基础关系:容器中可以包含组件;所有的容器都包含布局管理器(java.awt.Container类除外),用来指定容器中组件的位置和形状。图形类则提供在组件中显示文本和图形的方法。AWT中的许多操作都发生在组件、容器和布局管理器之间。,8.1.2 AWT组件类层次,组件是构成AWT的基础。AWT中包括大量的组件,其中大约有一半的类由java.awt.Component类扩展而来,所以,Component和它所支持的类是AWT的基础。,java.awt.Component类是一个抽象类,它为其派生类提供了许多功能。例如,一个组件可以有以下成员:图形对象、位置、尺寸、父容器、前景和背景色、最小/最大和首选尺寸等。,Java语言中,面板(Panel)、滚动条(Scrollbar)、按键(Button)、标签(Label)等等用户界面组件一般都派生自java.awt.Component类。图8.1是一些主要的AWT组件的结构层次。,图 8.1,8.1.3 容器和布局管理器,从java.awt.Container类扩展的类称为容器,Container也是一个从Component扩展的抽象类。顾名思义,容器就是用来包含组件的,一个容器可以包含多个组件,也可以使用容器将相关组件关联在一起,成为一个整体。合理的使用容器可以简化图形界面的设计,而且对于组件的显示安排也很有用。表8.2列出了从java.awt.Container类派生的AWT容器类。后面我们还会详细说明这些容器的使用。,表8.2 Container的子类,子类,说 明,Applet,Panel.Applet的扩展,使所有Applet的超类,Dialog,对话框(可模式化或非模式化Window的扩展),FieldDialog,用于选择文件的对话框,Frame,Window的扩展,应用程序的容器,可以有菜单和标题栏,Panel,Container的扩展,简单的容器,ScrollPane,滚动组件,Window,Container的扩展,没有菜单或边界,是Frame和Dialog的超类,容器只能记录包含的组件,而布局管理器则负责指定容器中组件的位置和大小。Java的布局管理器只需要确定组件和其他组件的相对位置,而不需要决定它的坐标,这样的安排令与平台无关的用户界面更易于实现。AWT中提供了五种布局管理器:, BorderLayout:该布局管理器将容器划分为东、南、西、北、中五个区域,当添加组件到容器中时,要指明将容器放置到哪一个区域中。, CarderLayout:该布局管理器将容器当作一个卡片栈,添加到容器中的每个组件都被放置在一个单独的卡片上,但每次只能显示一张卡片。, FlowLayout:该布局管理器将添加到容器中的组件按从上到下,从左到右的顺序依次排列。, GridLayout:该布局管理器将容器分成相同尺寸的网格,将添加到容器中的组件按从左到右、从上到下的顺序放置在每一个网格中。, GridBagLayout:该布局管理器也是将容器分成网格,它和GridLayout不一样的是,一个组件可以占据不止一个网格的位置。,关于布局管理器将在后面的章节中进行更深入的讨论,现在最重要的是站在高层次上理解布局管理器是如何协助容器管理组件的布局的。,8.1.4 可视组件的始祖类Component类,前面已经提到,Component类是大多数组件的超类,而Component类则直接继承Object类。Component类是一个抽象类,所以是不能直接使用,它为子类提供了非常多的虚拟方法。我们先简单介绍一下Component类提供的一些主要方法:, public boolean contains(int x, int y), public boolean contains(Point p),以上两个方法用于检查(x, y)或者对象p这个点是否落在组件的范围之内(其中,(x, y)坐标是相对于此组件的左上角的),是则返回true,否则返回false。, public Color getBackground(),返回组件的背景颜色,若组件没有设置背景颜色,则会返回其父组件(包含该组件的组件)的背景颜色。, public void setBackground(Color c),设置组件的背景颜色,若参数c的值为null,则会将背景颜色设为其父组件的背景颜色。, public Rectangle getBounds(),返回组件外框矩形的范围,这个范围定义了组件的宽、高和相对其容器的坐标位置。, public void setBounds(int x, int y, int width, int height), public void setBounds(Rectangle r),设置组件的位置、宽度和高度,可用于移动组件或改变其大小。除非此组件的容器没有使用布局管理器,否则这两个方法不生效。, public Component getComponentAt(int x, int y), public Component getComponentAt(Point p),判断组件或组件中的子组件(包含的组件)中,是否有一个包含(x, y)这个点的组件,是则返回该组件,否则返回null。该方法只检查一级子组件,如果点(x, y)在其子组件的子组件中,则只会返回该组件第一级的子组件。, public Cursor getCursor(),返回组件的鼠标光标对象。如果该组件没有设置鼠标光标,则返回其父组件的鼠标光标。, public void setCursor(Cursor cursor),设置组件的鼠标光标,例如将Button的光标改为手指、将Panel的光标改为放大镜等,当鼠标移动到这些对象上时会产生相应的变化。若参数为null,则设成和父组件的光标一样。, public Font getFont(),返回组件的字体,若组件没有设置字体,则返回其父组件的字体。, public void setFont(Font f),设置组件的字体,若参数f的值为null,则会采用其父组件的字体。, public Color getForeground(),返回组件的前景颜色,若组件没有设置前景颜色,则会返回其父组件的前景颜色。, public void setForeground(Color c),设置组件的前景颜色,若参数c的值为null,则会将前景颜色设为其父组件的前景颜色。, public Graphics getGraphics(),所有可视组件都有属于自己的Graphics对象可供画图,此方法返回该组件的Graphics对象。但要注意,若此组件还没有显示在屏幕上则会返回null。, public Point getLocation(), public int getX(), public int getY(),这三个方法用于返回组件矩形外框的左上角的坐标,这个坐标也是相对于其父组件而言的。getX()和getY()的作用与getLocation().x和getLocation().y或getBounds().x和getBounds().y一样,但推荐使用getX()和getY(),因为这两个方法无需内存分配。, public void setLocation(int x, int y), public void setLocation(Point p),移动该组件到左上角的由(x, y)或点对象p所指定的新位置,坐标也是相对于其父组件的。须注意的是,如果此组件使用了layout manager,这两个方法将不生效。, public Container getParent(),返回该组件的父组件,若没有父组件将返回null。, public Dimension getSize(), public int getWidth(), public int getHeight(),返回该组件的高度和宽度。与getX()和getY()一样,应该使用getWidth()和getHeight()而不是getSize().width和getSize().height或getBounds().width和 getBounds().height。, public void setSize(int width, int height), public void setSize(Dimentsion d),改变组件的高度与宽度。如果该组件使用了layout manager,这两个方法将无效。, public boolean isEnabled(),检查组件当前状态,可用状态则返回true,否则返回false。组件的可用状态指组件可以接收用户输入及产生事件的状态,如Windows中变灰的按键,就是非可用状态的。, public void setEnabled(boolean b),更改组件的状态为可用或不可用。, public boolean isVisible(),检查当组件的父组件为可见的时候,此组件是否为可见,是则返回true,否则返回false。除了顶层窗口(如Frame)外,组件默认初始为可见。, public void setVisible(boolean b),根据参数b的值改变窗口状态为可见或隐藏。, public void paint(Graphics g),在屏幕上绘制组件,当组件第一次显示或者需要重绘时该方法会自动被调用。如果需要改变某个基本组件的样式,可以通过重载这个函数来实现。重载这个函数不需要调用super.paint(g)。, public void repaint(),将组件重画一遍。当一个组件需要重画时,如从隐藏变为可见,或者被其他窗口遮住后那个窗口移开了,系统就会自动调用该方法,该方法又立即调用update()方法。, public void update(Graphics g),该方法的作用是将组件占据的矩形范围清成背景色,然后调用paint()方法重画这个组件。在动画技术中,经常需要用到一个叫Double Buffering(双缓冲技术)的技巧来避免画面的闪烁,这就需要重载update()和paint()这两个方法来实现。应注意的是,重载update()方法的时候,应该要调用super.update()方法或者手动调用paint()方法。, public String toString(),返回该组件的文字描述。,8.2 窗 口 类,AWT提供了三个在屏幕上显示窗口的组件:Window、Frame和Dialog。这三个组件都用于显示窗口,而且相互之间的区别也不明显,因此有时候很难确定到底使用哪个组件更好。为了帮助大家区分它们的不同用法,表8.3列出了各组件的属性特征。,表8.3 Window、Frame与Dialog组件的属性,属 性,Window,Frame,Dialog,模式化,不是,不是,不是(可设置),可调大小,不可,可,可,标题栏,无,有,有,边界,无,有,有,标题,无,有,有,菜单栏,无,有,无,焦点管理器,有,有,有,警告字符串,有,有,有,图表,无,有,无,定位到框架,可,不可,可,8.2.1 窗口(Window),java.awt.Window是三个窗口组件中最基本的组件,它实际上是Frame与Dialog组件的超类。窗口组件没有边界、标题栏与菜单栏,而且大小不可以调整。其次,如果用户在程序设计过程中,需要利用悬浮在其他组件上方的无边界矩形框显示信息,则窗口是最佳选择。常用窗口实现的界面包括:产品信息的封面(如Outlook等软件启动时,显示在屏幕中间且几秒后自动消失的封面窗口),提示帮助信息(如使用金山词霸等软件时,移动鼠标到某个英文单词上时自动弹出的解释信息)等。,下面我们通过一个例子来学习如何使用窗口类:,例8.1 FrameDemo.java,import java.awt.*;,public class SplashDemo extends Frame, Window window;,static public void main(String args),SplashDemo frame = new SplashDemo();,public SplashDemo(),window = new Window(this);,Dimension scmSize = Toolkit.getDefaultToolkit().getScreenSize();,int width = 300;,int height = 200;,window.setLocation(scmSize.width/2-(width/2),scmSize.height/2-(height/2);,window.setSize(width, height);,window.show();,window.toFront();,try Thread.currentThread().sleep(3000);,catch (Exception e) e.printStackTrace();,window.dispose();,System.exit(0); ,这是个使用Window的窗口在屏幕上显示一个矩形窗口类的实例,这个窗口没有边界、标题栏与菜单栏,在屏幕上停留3秒后自动消失。如果在窗口中加载一幅图片,则能实现一个类似Outlook的封面窗口(在窗口中加载图片的方法我们将在第9章中学习)。,程序中用到了工具类的方法Toolkit.getDefaultToolkit().getScreenSize()。Toolkit类是一个包含许多有用的本地工具方法的类。getScreenSize()方法的作用是取得显示器的像素尺寸。,程序的运行结果如图8.2所示。,图 8.2,8.2.2 框架(Frame),java.awt.Frame是Window的一个子类,它是带有标题栏和边界的窗口,而且允许调整大小。另外,用户还可以为框架附加一个菜单栏。用户在程序设计过程中,当程序窗口需要图表化或者需要包含菜单栏时,则可以选择使用框架组件。,构造一个框架后,可以用add()方法来给框架添加组件。框架的缺省布局管理器属性是BorderLayout。可以用setLayout()方式来改变布局管理器属性。,框架类中的Frame(String)构造方法创建一个由String规定标题的新的不可见的框架对象。,例8.2 FrameDemo.java,import java.awt.*;,public class FrameDemo extends Frame,public FrameDemo(String title),super(title);,public static void main(String agrs),FrameDemo frame = new FrameDemo(Demo Frame);,frame.setLocation(100, 100);,frame.setSize(500, 200);,frame.setVisible(true);,程序的运行结果如图8.3所示,它是一个具有标题、大小及背景颜色的框架。,图 8.3,8.2.3 对话框(Dialog),java.awt.Dialog也是Window的扩展类。与框架相同的是,对话框也拥有边界与标题栏,而且也可以调整大小;而与框架不同的是,对话框不支持附加菜单栏,而且对话框可以模式化属性设置,这是窗口和框架都不允许的。因此,如果用户在程序设计过程中需要创建一个临时窗口与用户交换信息时,使用模式对话框是最方便的。另外,AWT中还提供了Dialog类的一个常用的扩展类FileDialog(文件对话框)。它可以为用户选择一个待打开或保存的文件。,可以说对话框是介于窗口和框架之间的,对话框和框架相比各有特色。我们来看一个典型的对话框的例子。,例8.3 DialogDemo.java,import java.awt.*;,public class DialogDemo,public static void main(String agrs),Frame frame = new Frame();,Dialog dialog = new Dialog(frame, Demo Dialog, false);,dialog.setLocation(100, 100);,dialog.setSize(500, 100);,dialog.setVisible(true);,程序运行结果如图8.4所示。,图 8.4,文件对话框是文件选择设备的一个实现。它有自己的自由窗口以及窗口元素,并且允许用户浏览文件系统,以及为以后的操作选择一个特定的文件。例如:,例8.4 FileDialogDemo.java,import java.awt.*;,public class FileDialogDemo,public static void main(String args),Frame parentFrame = new Frame();,FileDialog d = new FileDialog(parentFrame, FileDialog);,d.setVisible(true); / block here until OK selected,String fname = d.getFile();,程序的运行结果如图8.5所示。,图 8.5,通常情况下,并不需要处理FileDialog的事件。上例中,调用setVisible(true)将阻塞事件,直至用户选择OK,这时,对话框会请求用户选择文件名,这个信息将作为一个String类型返回。,8.3 AWT基本组件,8.3.1 按钮(Button),按钮应该是我们最熟悉的可视组件之一,这个组件提供了“按下并动作”的基本用户界面功能。我们可以构造一个带文本标签的按钮,用来告诉用户它的作用。例如:,例8.5 ButtonDemo.java,import java.awt.*;,import java.awt.event.*;,public class ButtonDemo extends Frame implements ActionListener,Button button;,public static void main(String args),ButtonDemo frame = new ButtonDemo();,public ButtonDemo(),button = new Button(First);,button.addActionListener(this);,add(button);,setTitle(Button);,setSize(130, 100);,setVisible(true);,public void actionPerformed(ActionEvent evt),String arg = evt.getActionCommand();,if (arg.equals(First),System.out.println(Button press received.);,程序的运行结果如图8.6所示。,图 8.6,程序的运行结果如图8.6所示。,该例为Button注册了一个监听器。任何实现了被注册为监听者的ActionListener接口的类,它的actionPerformed()方法将在一个按钮被鼠标点击“按下”时被调用。,按钮被按下时调用的getActionCommand()方法在缺省情况下将返回触发组件的标签字符串(此处为按键的标签)。我们还可以通过setActionCommand()方法改变动作命令和标签。,8.3.2 复选框(Checkbox),Checkbox组件提供一种简单的“开/关”输入设备,它旁边有一个文本标签。应用方式如下:,例8.6 CheckboxDemo.java,import java.awt.*;,import java.awt.event.*;,public class CheckboxDemo extends Frame implements ItemListener,public static void main(String args),CheckboxDemo frame = new CheckboxDemo();,public CheckboxDemo(),setTitle(Checkbox Test);,setSize(300, 100);,setLayout(new FlowLayout();,Checkbox one = new Checkbox(One, true);,Checkbox two = new Checkbox(Two, false);,Checkbox three = new Checkbox(Three, true);,one.addItemListener(this);,two.addItemListener(this);,three.addItemListener(this);,add(one);,add(two);,add(three);,setVisible(true);,public void itemStateChanged(ItemEvent evt),String state = deselected;,if (evt.getStateChange() = ItemEvent.SELECTED),state = selected;,System.out.println(evt.getItem()+state);,程序运行结果如图8.7所示。,图 8.7,选取或不选取(取消)一个复选框的事件将被送往ItemListener接口。所传递的ItemEvent包含getStateChange()方法,它根据实际情况返回ItemEvent.DESELECTED或ItemEvent.SELECTED。getItem()方法将受到影响的复选框作为一个表示这个复选框标签的String对象返回。,程序中用到了一个布局管理器FlowLayout。前面我们已经提到了布局管理器的作用,此处为Frame添加FlowLayout的作用是让包含在其中的组件顺次排列。关于布局管理器的使用方法在8.5节中还将详细讨论。,8.3.3 复选框组单选框(Checkbox Group-Radio Button),复选框组提供了将多个复选框作为一个互斥的集合的方法,因此在任何时刻,这个集合中只有一个复选框的值是true。值为true的复选框就是当前被选中的复选框。你可以使用带有一个额外的CheckboxGroup参数的构造函数来创建一组中的各个复选框(正是这个CheckboxGroup对象将各个复选框连接成一组)。如果你这么做的话,那么复选框的外观会发生改变,而且所有和这个复选框组相关联的复选框将表现出“单选框”的行为。例如:,例8.7 CheckboxGroupDemo.java,import java.awt.*;,import java.awt.event.*;,public class CheckboxGroupDemo extends Frame implements ItemListener,public static void main(String args),CheckboxGroupDemo frame = new CheckboxGroupDemo();,public CheckboxGroupDemo(),setTitle(Checkbox Test);,setSize(300, 100);,setLayout(new FlowLayout();,CheckboxGroup cbg = new CheckboxGroup();,Checkbox one = new Checkbox(One, false, cbg);,Checkbox two = new Checkbox(Two, false, cbg);,Checkbox three = new Checkbox(Three, true, cbg);,one.addItemListener(this);,two.addItemListener(this);,three.addItemListener(this);,add(one);,add(two);,add(three);,setVisible(true);,public void itemStateChanged(ItemEvent evt),String state = deselected;,if (evt.getStateChange() = ItemEvent.SELECTED) state = selected;,System.out.println(evt.getItem()+state);,程序运行结果如图8.8所示。,图 8.8,8.3.4 下拉列表(Choice),下拉列表组件提供了一个简单的“从列表中选取一个”类型的输入方式。例如:,例8.8 ChoiceDemo.java,import java.awt.*;,import java.awt.event.*;,public class ChoiceDemo extends Frame implements ItemListener,public static void main(String args),ChoiceDemo frame = new ChoiceDemo();,public ChoiceDemo(),setSize(100, 150);,Choice choice = new Choice();,choice.add(First);,choice.add(Second);,choice.add(Third);,choice.addItemListener(this);,add(choice);,setVisible(true);,public void itemStateChanged(ItemEvent evt),String state = deselected;,if (evt.getStateChange() = ItemEvent.SELECTED),state = selected;,System.out.println(evt.getItem()+state);,程序运行结果如图8.9所示。,图 8.9,点击下拉列表组件时,它会显示一个列表,列表中包含了所有加入其中的条目。注意所加入的条目是String对象。ItemListener接口用来观察下拉列表组件的变化,其细节和复选框的相同。,8.3.5 标签(Label),一个标签对象显示一行静态文本。程序员可以改变文本,但用户不能改变。标签没有任何特殊的边框和装饰。例如:,例8.9 LabelDemo.java,import java.awt.*;,public class LabelDemo extends Frame,public static void main(String args),LabelDemo frame = new LabelDemo();,frame.setSize(100, 50);,图 8.10,Label label = new Label(Hello);,frame.add(label);,frame.setVisible(true);,程序运行结果如图8.10所示。,标签通常不处理事件,但也可以按照和画布相同的方式来处理事件。也就是说,只有调用了requestFocus()方法后,才能可靠地检取击键事件。,8.3.6 文本域(Textfield),文本域是一个单行的文本输入设备,通常用于获取一行用户输入的字符,如用户名、密码的输入等。例如:,例8.10 TextfieldDemo.java,import java.awt.*;,import java.awt.event.*;,public class TextfieldDemo extends Frame implements ActionListener,public static void main(String args),TextfieldDemo frame = new TextfieldDemo();,public TextfieldDemo(),setSize(300, 100);,setLayout(new GridLayout(2, 2);,Label l1 = new Label(User:);,TextField user = new TextField();,user.addActionListener(this);,Label l2 = new Label(Password:);,TextField pass = new TextField();,pass.addActionListener(this);,add(l1);,add(user);,add(l2);,add(pass);,setVisible(true);,public void actionPerformed(ActionEvent evt),String arg = evt.getActionCommand();,System.out.println(+arg);,因为只允许有一行文字,所以当按下Enter或Return键时,ActionListener可以通过actionPerformed()检测到这个事件。如果需要,还可以增加其他的组件监听者。,除了注册一个ActionListener,你还可以注册一个TextListener来接收关于个别击键的通知。它的回调方法是textValueChanged(TextEvent)。程序运行结果如图8.11所示。,图 8.11,8.3.7 文本区(TextArea),文本区是一个多行多列的文本输入设备。你可以用setEditable(boolean)将它设置成只读的。文本区将显示水平和垂直的滚动条。下面这个范例创建了一个4行30字符的文本,最初它含有Hello!字符。,例8.11 TextAreaDemo.java,import java.awt.*;,import java.awt.event.*;,public class TextAreaDemo extends Frame implements TextListener,public static void main(String args),TextAreaDemo frame = new TextAreaDemo();,public TextAreaDemo(),setSize(300, 100);,TextArea area = new TextArea(Hello!, 4, 30);,area.addTextListener(this);,add(area);,setVisible(true);,public void textValueChanged(TextEvent evt), System.out.println(+evt);,用addTexListener指定的监听者将以和文本域相同的方式接收到关于击键的通知。,可以给文本区增加一般的组件监听者,然而,由于文本是多行的,按下Enter键将导致把另一个字符送入缓冲。如果你需要识别“输入的结束”,你可以在文本区旁放置一个“应用”或“确认”按钮,以便用户指明“输入的结束”。程序运行结果如图8.12所示。,图 8.12,8.3.8 列表(List),一个列表可将各个文本选项显示在一个区域中,这样就可以在同时看到若干个条目。列表可以滚动,并支持单选和多选两种模式。例如:,例8.12 ListDemo.java,import java.awt.*;,import java.awt.event.*;,public class ListDemo extends Frame,implements ItemListener, public static void main(String args),ListDemo frame = new ListDemo();,public ListDemo(), setSize(100, 200);,List list = new List(4, true);,list.add(First);,list.add(Second);,list.add(Third);,list.add(Fourth);,list.addItemListener(this);,add(list);,setVisible(true);,public void itemStateChanged(ItemEvent evt),String state = deselected;,if (evt.getStateChange() = ItemEvent.SELECTED),state = selected;,System.out.println(evt.getItem()+state);,构造函数的数值参数定义了按可见列计算的列表高度。这个值也可能被布局管理器覆盖。一个值为true的布尔型参数表明这个列表允许用户作多个选择。,选取或取消一个条目时,AWT将一个ItemEvent的实例送往列表。用户双击滚动列表中的一个条目时,单选模式和多选模式的列表都会产生一个ActionEvent,根据每个平台的约定来决定列表中的条目是否被选取。对于Unix/Motif环境,单击会加亮列表中的一个条目,只有双击才会触发列表事件(选取条目)。,程序运行结果如图8.13所示。,图 8.13,8.3.9 画布(Canvas),画布提供了一个空白(背景色)的空间。除非你用setSize()显式地定义它的大小,否则它的大小就是00。,画布的空间可以用来绘图、显示文本、接收键盘或鼠标的输入。通常,画布用来提供一个一般的绘图空间或者为客户组件提供工作区域。,画布可以“监听”所有适用于一个普通组件的事件。特别地,你还可能想增加KeyListener、MouseMotionListener和MouseListener对象,以允许以某种方式对用户输入作出反应。,注:如要在画布中接收键盘事件,必须调用画布的requestFocus()方法。如果缺少这个步骤,一般不能将击键“导向”画布。而且键盘事件会送往另一个组件,或整个地丢失。,下面是画布的一个范例。用户每击一次键,这个程序就改变一次画布的颜色。,例8.13 CanvasDemo.java,import java.awt.*;,import java.awt.event.*;,import java.util.*;,public class CanvasDemo extends Canvas implements KeyListener, int index;,Color colors = Color.red, Color.green, Color.blue ;,public static void main(String args),Frame f = new Frame(Canvas);,CanvasDemo mc = new CanvasDemo();,f.add(mc,BorderLayout.CENTER);,f.setSize(150, 150);,mc.requestFocus();,mc.addKeyListener(mc);,f.setVisible(true); ,public void paint(Graphics g),g.setColor(colorsindex);,g.fillRect(0,0,getSize().width,getSize().height);,图 8.14,public void keyTyped(KeyEvent ev),index+;,if (index = colors.length) index =0;,repaint(); ,public void keyPressed(KeyEvent ev),public void keyReleased(KeyEvent ev),程序运行结果如图8.14所示。,8.3.10 面板(Panel),像Frame一样,Panel提供空间来连接任何GUI组件,包括其他面板。每个面板都可以有它自己的管理程序。一旦一个面板对象被创建,为了能被看见,必须将它添加到窗口或框架对象上。用Container类中的add()方式可以做到这一点。,下面的程序创建了一个小的黄色面板,并将它加到了一个框架对象上。,例8.14 FrameWithPanel.java,import java.awt.*;,public class FrameWithPanel extends Frame,public FrameWithPanel (String str),super (str);,public static void main (String args),FrameWithPanel fr = new FrameWithPanel (Frame with Panel);,Panel pan = new Panel();,fr.setSize(200,200);,fr.setBackground(Color.blue);,fr.setLayout(null);,pan.setSize (100,100);,pan.setBackground(Color.yellow);,fr.add(pan);,fr.setVisible(true);,程序的运行结果如图8.15所示。,图 8.15,8.3.11 滚动面板(ScrollPane),滚动面板提供了一种不能作为自由窗口的通用容器,它总是和一个容器相关联(例如框架)。滚动面板提供了到一个更大的区域的视窗以及操纵这个视窗的滚动条。例如:,例8.15 ScrollPaneDemo.java,import java.awt.*;,import java.awt.event.*;,public class ScrollPaneDemo,public static void main(String args),Frame f = new Frame(ScrollPane);,Panel p = new Panel();,ScrollPane sp = new ScrollPane();,p.setLayout(new GridLayout(3, 4);,for (int i = 0; i 12; i+),p.add(new Button(Button+i);,sp.add(p);,f.add(sp, Center);,f.setSize(150, 150);,f.setVisible(true);,图 8.16,程序运行结果如图8.16所示。,滚动面板创建和管理滚动条,并持有一个组件。它不能控制自己所用的布局管理器,但可以将一个面板加入到滚动面板中,配置面板的布局管理器,并在那个面板中放置你的组件。,通常,滚动面板上的事件均通过滚动面板所包含的组件进行处理。,8.4 菜 单,菜单与其他组件有一个重要的不同:不能将菜单添加到一般的容器中,而且不能使用布局管理器对它们进行布局,只能将菜单加到一个菜单容器中。你可以通过使用setMenuBar()方法将菜单放到一个框架中,从而启动一个菜单“树”之后,便可以将菜单加到菜单条中,并将菜单或菜单项加到菜单中。,弹出式菜单是一个例外,因为它们可以以浮动窗口形式出现,因此不需要布局。,8.4.1 帮助菜单,菜单条的一个特性是你可以将其中一个菜单指定为帮助菜单。这可以用setHelpMenu(Menu) 来做到,但必须先加入到菜单条中,它才会和本地平台的帮助菜单以同样的方式被处理。对于X/Motif类型的系统,被设定为帮助菜单的菜单条将显示在菜单条的最右边。,8.4.2 菜单条(MenuBar),一个菜单条组件是一个水平菜单。它只能加入到一个框架中,并成为所有菜单树的根。在一个时刻,一个框架可以显示一个菜单条。然而,你可以根据程序的状态修改菜单条,这样就可以在不同的时刻显示不同的菜单。例如:,Frame f = new Frame(MenuBar);,MenuBar mb = new MenuBar();,f.setMenuBar(mb);,菜单条不支持监听者。作为普通菜单行为的一部分,在菜单条的区域中发生的预期事件会被自动处理。,8.4.3 菜单(Menu),菜单组件提供了一个基本的下拉式菜单。它可以加入到一个菜单条或者另一个菜单中。例如:,MenuBar mb = new MenuBar();,Menu m1 = new Menu(File);,Menu m2 = new Menu(Edit);,Menu m3 = new Menu(Help);,mb.add(m1);,mb.add(m2);,mb.setHelpMenu(m3);,f.setMenuBar(mb);,生成的菜单如图8.17所示。,图 8.17,8.4.4 菜单项(MenuItem),菜单项组件是菜单树的文本“叶”结点。它们通常被加入到菜单中,以构成一个完整的菜单。例如:,例8.16 MenuBarDemo.java,import java.awt.*;,import java.awt.event.*;,public class MenuBarDemo extends,Frame implements ActionListener,public static void main(String args),MenuBarDemo frame = new MenuBarDemo();,public MenuBarDemo(), setSize(200, 200);,MenuBar mb
展开阅读全文