1、第9章 Java图形用户界面,第9章 Java图形用户界面,教学提示:在Java的图形化程序设计中,需要有大量的组件来支持。Component 是许多组件类的父类,它封装了组件通用的方法和属性,如组件大小、显示位置、前景色和背景色、边界、可见性等。容器(Container)也是一个类,它是Component 的子类,它的主要功能是容纳其他组件和容器,而每个容器都有一个默认布局管理器。 本章主要介绍:Java中常用的非容器组件类、容器组件类以及用于管理容器布局的布局管理器等,它们是进行图形化设计的基础,从类对象的创建、类的属性、事件类型等方面来综合掌握这些类的应用。本章通过介绍常用类的使用方法,
2、使读者能够进行窗体的设计,并运用事件处理机制来处理事件。,第9章 Java图形用户界面,9.1 容器与基本控件 9.2 布局管理器 9.3 Java中键盘事件和鼠标事件 9.4 彩色列表框实例 9.5 课后练习,9.1 容器与基本控件,9.1.1 窗口 9.1.2 面板和画布 9.1.3 菜单 9.1.4 按钮 9.1.5 文本框和文本域 9.1.6 标签,9.1 容器与基本控件,本节将重点介绍Java的窗口编程中几个常用的控件,熟悉和掌握它们将有利于很好地进行Windows程序开发。,9.1.1 窗口,1. Frame 的创建 Frame 类提供了两个构造方法来分别创建不带标题和带标题的Fr
3、ame 窗口。 public Frame():创建一个不可见的无标题Frame 窗口。 public Frame(String title):创建一个不可见的指定标题的Frame 窗口。,9.1.1 窗口,2. Frame 的常用方法 由于Component、Container、Window和Frame 依序存在父子类关系,除了可以继承其父类的非私有方法外,Frame 类又提供了相应的方法来改变Frame 窗口的属性,如表9-1所示。,9.1.1 窗口,表9-1 Frame类中常用的方法,9.1.1 窗口,3. Frame 与窗口事件 Frame 是一个带有标题和缩放角的窗口,有自己的外边框和
4、标题,创建Frame 时可以指定其窗口标题。每个Frame 在其右上角都有3 个控制图标,分别代表将窗口最大化、最小化和关闭的操作,其中,最大化和最小化操作Frame 可自动完成,而关闭窗口的操作不能通过单击关闭图标实现,必须通过事件响应来关闭窗口,在前面含有窗口的示例中,都不能通过关闭按钮来退出程序,只能使用Ctrl+Alt+Del 键来强行退出。,9.1.1 窗口,窗口事件是由于窗口收到窗口级事件而产生的,该事件对应的接口名称是WindowListener,该接口的定义如下: public interface WindowListener extends EventListener pub
5、lic void windowClosing(WindowEvent e); /退出窗口的语句写在本方法中public void windowOpened(WindowEvent e); /窗口打开时调用public void windowIconified(WindowEvent e); /窗口图标化时调用public void windowDeiconified(WindowEvent e); /窗口非图标化时调用public void windowClosed(WindowEvent e); /窗口关闭时调用public void windowActivated(WindowEvent
6、e); /窗口激活时调用public void windowDeactivated(WindowEvent e); /窗口非激活时调用 ,9.1.1 窗口,【例9.1】MyFrame类可以实现两种退出运行程序、关闭窗口的方法。一种是通过用户设置的Exit 按钮,另一种是使用窗口关闭按钮。其中CloseFrame 是用来关闭窗口的类。程序如下。 import java.awt.*; import java.awt.event.*; public class MyFrame implements ActionListener public static void main(String args)
7、Frame f=new Frame(“Hello!“);Button button=new Button(“exit“);f.setLayout(new FlowLayout();f.add(button);button.addActionListener(new MyFrame(); /注册ActionListener监听器f.setBounds(0,0,260,120);f.addWindowListener(new CloseFrame(); /注册WindowListener监听器f.setVisible(true);/重写ActionListener接口中的actionPerform
8、ed()方法,9.1.1 窗口,public void actionPerformed(ActionEvent e)if(e.getActionCommand()=“exit“)System.exit(1); /定义处理窗口事件的类CloseFrame,实现WindowListener接口 class CloseFrame implements WindowListener public void windowClosing(WindowEvent e)System.exit(1); /退出系统public void windowActivated(WindowEvent e)public v
9、oid windowDeactivated(WindowEvent e)public void windowClosed(WindowEvent e)public void windowOpened(WindowEvent e)public void windowIconified(WindowEvent e)public void windowDeiconified(WindowEvent e) 该程序的运行结果如图9-1所示。,9.1.1 窗口,图9-1 运行结果(例9.1),9.1.2 面板和画布,1. 面板和画布的创建 Panel 类提供了两个构造方法来创建面板对象。 public P
10、anel():创建一个默认布局管理器的面板对象。 public Panel(LayoutManager layout):创建一个指定布局管理器的面板对象。 面板对象创建之后,就可以运用容器对象的add()方法将该面板加入其他的容器中。当然也可以嵌套面板,即一个面板包含一个或多个其他的面板,例如: Panel panel1=new Panel(); Panel panel2=new Panel(); Panel panel3=new Panel(); panel1.Add(panel2); /把panel2和panel3加入panel1中 panel1.Add(panel3); add(pane
11、l1); /加入当前小应用程序中,9.1.2 面板和画布,画布组件可以通过下面的构造方法创建: public Canvas() 当程序运行后,将出现一块矩形区域的画布,Canvas 组件默认尺寸为00,所以必须保证至少在画布中实现自己的尺寸方法。,9.1.2 面板和画布,2. 面板和画布的使用 Canvas 组件的常用方法为public void paint(Graphics g),画布是一种通用组件,它本身不具有任何功能,也不处理任何事件,在用户使用画布时应该在程序中派生它的子类,并覆盖Canvas 类的paint()方法,就可以在画布上面绘制有关的图形。Canvas 组件监听各种鼠标、键盘
12、事件。当在Canvas 组件中输入字符时,必须先调用requestFocus()方法。 画布和面板都可以“监听”所有适用于一个普通组件的事件,当然也可以引发键盘和鼠标事件,以允许以某种方式对用户输入作出反应。,9.1.2 面板和画布,【例9.3】创建两个面板,每个面板含有两个组件,程序文件名MyPanel.java。程序如下。 import java.awt.*; class MyPanel public static void main(String args)Frame f=new Frame(“Hello!“);Panel panel1=new Panel(); /定义并创建面板对象pa
13、nel1Panel panel2=new Panel(); /定义并创建面板对象panel2Checkbox check1=new Checkbox(“BOLD“);Checkbox check2=new Checkbox(“ITALIC“);CheckboxGroup group=new CheckboxGroup(); /定义并创建复选按钮组Checkbox check3=new Checkbox(“red“,group,false);Checkbox check4=new Checkbox(“blue“,group,false);/把复选按钮check1和check2添加到面板容器pan
14、el1panel1.add(check1);panel1.add(check2);/把复选按钮check3和check4添加到面板容器panel2panel2.add(check3);panel2.add(check4);f.setLayout(new FlowLayout();/把面板panel1和panel2添加到窗体中,9.1.2 面板和画布,f.add(panel1);f.add(panel2);f.setBounds(0,0,280,150);f.setVisible(true); 运行效果如图9-2 所示。图9-2 运行结果(例9.3),9.1.2 面板和画布,【例9.4】画布的实
15、现和应用,程序文件名CanvasApp.java。程序如下。 import java.awt.*; import java.awt.event.*; class CanvasApp public static void main(String args)Frame f=new Frame(“Hello!“);/创建MyCanvas对象,并初始化画图颜色为红色MyCanvas cv=new MyCanvas(Color.red);cv.setSize(100,100); /设置画布的大小f.setSize(200,200);f.add(cv);f.setLayout(new FlowLayout
16、();f.setVisible(true); /定义画布MyCanvas类 class MyCanvas extends Canvas Color myColor; /定义画图的颜色对象/构造方法,初始化画图颜色public MyCanvas(Color drawColor),9.1.2 面板和画布,myColor=drawColor;public void paint(Graphics g)int diameter,xPoint,yPoint; /定义圆的直径和圆的左上角坐标变量Dimension currentSize=getSize(); /获取当前画布的尺寸/圆的直径取当前画布尺寸中的
17、小值if (currentSize.widthcurrentSize.height)diameter=currentSize.height;elsediameter=currentSize.width;g.setColor(myColor); /设置绘图的颜色xPoint=(currentSize.width-diameter)/2; /左上角x坐标yPoint=(currentSize.height-diameter)/2; /左上角y坐标g.fillOval(xPoint,yPoint,diameter,diameter); /填充一个圆 该程序的运行结果如图9-3 所示。,9.1.2 面
18、板和画布,图9-3 运行结果(例9.4),9.1.3 菜单,1. 菜单条(MenuBar) 菜单条是一种水平菜单,它只能被添加到Frame 对象中,作为整个菜单树的根基。其主要功能是被用来放置Menu 组件。创建菜单条的构造方法为: public MenuBar() 把菜单条添加到指定的窗口中,常常使用窗口类的setMenuBar()方法来实现。下面的程序可以把一个菜单条mb添加到窗口fr中。 Frame fr = new Frame(“MenuBar“); MenuBar mb = new MenuBar(); /创建菜单条对象 fr.setMenuBar(mb); /设置窗体的菜单条为mb
19、 fr.setSize(150,100); fr.setVisible(true); 菜单条不支持监听器,因为在其中所发生的各类事件将由菜单项处理。,9.1.3 菜单,2. 菜单(Menu) Menu 类的主要功能是被用来放置 MenuItem、MenuShortCut 等组件,它可以被添加到MenuBar 中或其他Menu 中。常用菜单条的add()方法把菜单对象添加到菜单条中。下面的程序段实现了在窗体中添加一个菜单条,并在菜单条中加入3 个菜单的示例效果。 Frame fr = new Frame(“MenuBar“); MenuBar mb = new MenuBar(); fr.set
20、MenuBar(mb); /创建3个菜单对象m1,m2,m3 Menu m1 = new Menu(“File“); Menu m2 = new Menu(“Edit“); Menu m3 = new Menu(“Help“); mb.add(m1); /把菜单添加到菜单条中 mb.add(m2);,9.1.3 菜单,图9-4 菜单条的运行结果,9.1.3 菜单,3. 菜单项(MenuItem) 菜单项是菜单树中的“文本叶子”,菜单项通常被添加到一个菜单中。对于MenuItem对象可以添加ActionListener,使其能够完成相应的操作。创建菜单项对象常用的构造方法有以下几个。 publi
21、c MenuItem():创建一个没有标签和键盘快捷键的菜单项。 public MenuItem(String label):创建一个有标签而没有键盘快捷键的菜单项。 public MenuItem(String label, MenuShortcut s):创建一个有标签和键盘快捷键的菜单项。 MenuItem类也提供了deleteShortcut()、getLabel()、isEnabled()、setEnabled()、setLabel()和setShortcut()等方法实现对菜单项的设置。,9.1.3 菜单,对上面的程序段进行菜单项的补充,就可以创建一个带有菜单项的示例效果。 Men
22、u m1 = new Menu(“File“); MenuItem mi1 = new MenuItem(“Save“); MenuItem mi2 = new MenuItem(“Load“); MenuItem mi3 = new MenuItem(“Quit“); m1.add(mi1); m1.add(mi2); m1.add(mi3); 运行效果如图9-5 所示。,9.1.3 菜单,图9-5 添加菜单项,9.1.3 菜单,4. 分隔条的设置 除菜单项以外,用户还可以在菜单中添加子菜单和菜单分隔符,分隔符是出现在菜单中的一条线,用于将菜单分成多个部分。可以调用addSeparator(
23、)方法来添加分隔符。 在上面的程序代码段中再增加m1.addSeparator()语句后的运行效果如图9-6所示。图9-6 加分隔线,9.1.3 菜单,5. 子菜单的创建 要想创建子菜单,只需要创建一个新的菜单实例并把它加到当前的菜单中即可。 【例9.5】二级菜单设计举例。程序如下。 MenuBar mb = new MenuBar(); /创建菜单条 /创建3个菜单对象 Menu m1 = new Menu(“File“); Menu m2 = new Menu(“Edit“); Menu m3 = new Menu(“Help“); /创建一个作为子菜单的菜单对象 Menu sub = n
24、ew Menu(“sub menu“); /向该子菜单中添加两个菜单项 sub.add(new MenuItem(“sub item1“); sub.add(new MenuItem(“sub item“); /创建3个菜单项 MenuItem mi1 = new MenuItem(“Save“); MenuItem mi2 = new MenuItem(“Load“); MenuItem mi3 = new MenuItem(“Quit“); /给菜单条添加3个菜单 mb.add(m1); mb.add(m2);,9.1.3 菜单,mb.setHelpMenu(m3); /给m1菜单对象添加
25、菜单项、分割符和二级子菜单sub m1.add(mi1); m1.add(mi2); m1.addSeparator(); m1.add(sub); m1.add(mi3); 运行效果如图9-7所示。图9-7 添加子菜单(例9.5),9.1.3 菜单,6. 使用菜单子项快捷键 在用构造方法MenuItem(String label, MenuShortcut s)创建MenuItem 对象时,可以为其设置一个对应的快捷键,MenuShortcut 类提供了两个构造方法用来创建快捷键。 (1) public MenuShortcut(int key):以指定的键符创建功能选项快捷键。 (2) M
26、enuShortcut(int key, boolean useShiftModifier):以指定的键符创建功能选项快捷键并可指定是否使用Shift 键。,9.1.3 菜单,【例9.6】菜单设计举例,程序如下。 import java.awt.*; import java.awt.event.*; class MyMenu implements ActionListener public static void main(String args)Frame fr = new Frame(“MenuBar“);MenuBar mb = new MenuBar();fr.setMenuBar(m
27、b);Menu m1 = new Menu(“File“);Menu m2 = new Menu(“Edit“);Menu m3 = new Menu(“Help“);/设置菜单项的快捷键MenuItem mi1=new MenuItem(“Save“,new MenuShortcut(KeyEvent.VK_S);MenuItem mi2=new MenuItem(“Load“,new MenuShortcut(KeyEvent.VK_O);MenuItem mi3=new MenuItem(“Quit“,new MenuShortcut(KeyEvent.VK_X);,9.1.3 菜单,m
28、b.add(m1);mb.add(m2);mb.setHelpMenu(m3);m1.add(mi1);m1.add(mi2);m1.addSeparator();m1.add(mi3);mi3.addActionListener(new MyMenu(); /对Quit菜单项注册动作事件监听器fr.addWindowListener(new CloseFrame(); /对窗体注册窗体事件监听器fr.setSize(150,150);fr.setVisible(true);,9.1.3 菜单,public void actionPerformed(ActionEvent e)if(e.get
29、ActionCommand()=“Quit“)System.exit(1); 效果如图9-8所示。图9-8 给菜单加快捷键(例9.6),9.1.4 按钮,1. 按钮的创建 按钮Button 类提供了两个构造方法来创建按钮对象,所以在创建按钮时用户只需要决定是否给按钮填写标签即可。 (1) public Button():创建一个没有标签的按钮对象。 (2) public Button(String label):创建一个有标签的按钮对象。,9.1.4 按钮,当一个按钮创建后,需要把按钮加进容器中,如: Button myButton=new Button(“OK“); add(myButton
30、); Button类除了可以使用继承于父类的方法外,对其属性进行操作的方法主要还有两个。 (1) public String getLabel():返回按钮的标签文本。 (2) public void setLabel(String label):重新设置按钮的标签文本。,9.1.4 按钮,2. 按钮的事件响应 Java采用将事件源和监听器分开的委托事件模型来处理事件,不同的事件由不同的监听器处理。图形用户界面中每个可能产生事件的组件都被称为“事件源”,如文本框、按钮、菜单等,实现事件响应的对象称为“监听者”,监听者可以是任何类,但它必须实现与事件类型相对应的监听接口,并被事件源注册,这样监听
31、器才能时刻监听事件源上发生的相关事件,一旦该事件类型与自己所负责处理的事件类型一致,就马上进行处理。当一个按钮对象被单击后,该按钮对象就是事件源,将引发ActionEvent 事件,对该事件的处理可以结合事件处理模型来进行。,9.1.4 按钮,对于ActionEvent 事件类型,它所对应的监听接口是ActionListener,我们必须定义相应的事件监听器类来实现ActionListener 接口;在实现ActionListener 接口的监听器类中要重写actionPerformed()方法,把事件发生后要完成的功能在该方法中实现;事件源对象通过addActionListener(监听器类
32、对象)来注册监听器,完成授权处理。 当有多个按钮被监听器监听时,为了可以使用ActionEvent类中的getActionCommand()方法区分当前事件产生的事件源,该方法返回所单击按钮上的标签字符串,而按钮上的标签用户是已知的,通过equals()方法进行字符串恒等比较,就可以确定哪个按钮被单击了。,9.1.4 按钮,3. 复选按钮的创建 复选按钮Checkbox 组件可以提供简单的“on/off”开关,同时在旁边还可以显示一个文本标签。 创建复选按钮对象的构造方法有以下几个。 (1) public Checkbox():创建不带标签的复选按钮。 (2) public Checkbox(
33、String label):创建带标签的复选按钮。 (3) public Checkbox(String label, boolean state):创建带标签且指定选择状态的复选按钮。,9.1.4 按钮,在创建带标签的复选按钮对象时,标签文本要能够体现复选按钮的意义和作用。Checkbox类直接派生于Component类,在对复选按钮对象操作时,常用的方法有以下几个。 (1) public String getLabel():获取复选按钮的标签。 (2) public void setLabel(String label):重置复选按钮的标签。 (3) public boolean getS
34、tate():获取复选按钮的选择状态。 (4) public void setState(boolean state):重置复选按钮的选择状态。,9.1.4 按钮,4. 复选按钮的事件响应 复选按钮被单击后,如果原来选中则变为未选中,反之亦然,同样,如果不给复选按钮对象注册监听器,外观虽然发生变化,但是不会执行用户所指定的功能。 复选按钮类响应的主要事件是项目事件,即ItemEvent 事件,单击复选按钮就会触发ItemEvent 事件,ItemEvent 事件类所对应的监听接口是 ItemListener,在该接口中只有一个方法itemStateChanged(ItemEvent e)。,9
35、.1.4 按钮,5. 单选按钮的常用方法 单选按钮是复选框的特例,没有单独的单选按钮类存在。用户可以通过把一组复选按钮放置在同一个复选按钮组中而创建一套单选按钮组。 CheckboxGroup 类提供了一个构造方法来创建复选按钮组: public CheckboxGroup() CheckboxGroup 类提供的用来管理复选按钮组的常用方法如下。 public Checkbox getSelectedCheckbox():得到当前选中的复选按钮。 public void setSelectedCheckbox(Checkbox box):设置被选中的复选按钮对象。 创建单选按钮的方法如下。
36、public Checkbox(String label, boolean state, CheckboxGroup group) public Checkbox(String label, CheckboxGroup group, boolean state),9.1.4 按钮,6. 单选按钮的事件响应 单选按钮的事件响应与复选按钮相同,单击单选按钮时,相应的项目事件将被调用。在事件处理方法itemStateChanged(ItemEvent e)中,利用ItemEvent 类的getSource()方法返回所选择的单选按钮的对象名,也可利用ItemEvent 类的getItem()方法返回
37、所选择的单选按钮的标签值来确定事件源对象。用Checkbox 类的getState()方法来判断当前事件源对象的选中状态,也可用ItemEvent 类的getStateChange()方法判断事件源的选中状态。,9.1.4 按钮,【例9.8】单、复选按钮的实现举例,程序如下。 import java.awt.*; import java.awt.event.*; class MyCheck implements ItemListener /实现ItemListener static TextField text1; /定义静态文本框对象text1static Checkbox check1;
38、/定义静态复选按钮对象check1static Checkbox check2; /定义静态复选按钮对象check2static Checkbox check3; /定义静态复选按钮对象check3public static void main(String args)Frame f=new Frame(“Hello!“);text1=new TextField(“Please control me!“,20);check1=new Checkbox(“BOLD“); /创建复选按钮对象check1CheckboxGroup group=new CheckboxGroup(); /创建复选按钮
39、组对象group/创建复选按钮对象check2和check3并加入复选按钮组group中,/初始时按钮的状态为未选中check2=new Checkbox(“red“,group,false);check3=new Checkbox(“blue“,group,false);f.setLayout(new FlowLayout();,9.1.4 按钮,f.add(text1);f.add(check1);f.add(check2);f.add(check3);/对复选按钮添加监听器check1.addItemListener(new MyCheck();check2.addItemListene
40、r(new MyCheck();check3.addItemListener(new MyCheck();text1.setFont(new Font(“宋体“,Font.PLAIN,15); /文本框对象text1的字体f.setBounds(0,0,200,100);f.setVisible(true);/重写ItemListener接口中的itemStateChanged()方法public void itemStateChanged(ItemEvent e)/用复选按钮控制文本框text1的字体为粗或者常规if (e.getSource()=check1)if (e.getStateC
41、hange()=1)text1.setFont(new Font(“宋体“,Font.BOLD,15);else,9.1.4 按钮,text1.setFont(new Font(“宋体“,Font.PLAIN,15);/用单选按钮控制文本框text1的字体颜色为红色或是蓝色if (e.getSource()=check2)text1.setForeground(Color.red);if (e.getSource()=check3) text1.setForeground(Color.blue); 程序运行结果如图9-10所示。图9-10 运行结果(例9.8),9.1.5 文本框和文本域,1. 文本框和文本区的创建 TextField类提供了多种构造方法,用于创建文本框组件的对象。常见的构造方法的使用如下。 public TextField():创建一个空的文本框对象。 public TextField(int columns):创建一个能容纳columns 个字符的空文本框对象。 public TextField(String text):创建一个初始化文本为text 的文本框对象。 public TextField(String text, int columns):创建一个长度为columns 且初始化文本为text 的文本框对象。,