Presentation is loading. Please wait.

Presentation is loading. Please wait.

第9章 图形用户界面(GUI)设计.

Similar presentations


Presentation on theme: "第9章 图形用户界面(GUI)设计."— Presentation transcript:

1 第9章 图形用户界面(GUI)设计

2 学习导读 首先,我们学习一些基本的图形编程知识,包括窗口的显示及外观设置、在窗口中显示文字和图像等; 接下来,介绍Java的事件处理机制,例如如何在程序中接收并处理如键盘按键和鼠标点击等“事件”; 最后,系统地介绍图形用户界面中常用组件的用法,如布局管理器、文本框、复选框、菜单、对话框等。

3 教学重点与难点 容器、组件、布局和观感 Java的事件处理机制 布局管理器 各种Awt组件的用法 各种Swing组件的用法
窗口事件、键盘事件、鼠标事件的处理

4 9.1图形用户界面设计概述 Java 1.0的出现带来了抽象窗口工具箱(AWT)。设计目标是希望构建一个通用的GUI,使得利用它编写的程序能够运行在所有的平台上,以实现Sun公司提出的口号“一次编写,随处运行”。 在Java 1.2中,Sun公司推出了新的用户界面库:Swing。相对AWT来说,Swing功能更强大、使用更方便,它的出现使得Java的图形用户界面上了一个台阶。 但是,Swing并没有代替AWT。在Java 1.1中,AWT事件处理模型有了根本改变。Swing使用的仍然是Java 1.1的事件处理模型。

5 9.1.1 GUI支持包和简单GUI程序例 1.java.awt包 2. javax.swing包
Java语言在java.awt包中提供了大量地进行GUI设计所使用的类和接口,包括绘制图形、设置字体和颜色、控制组件、处理事件等内容,AWT是Java语言进行GUI程序设计的基础。 2. javax.swing包 Swing包是Java基础类库(Java Foundation Classes,JFC)的一部分。Swing提供了从按钮到可分拆面板和表格的所有组件。

6 AWT组件和对应的Swing组件,从名称上很容易记忆和区别。
例如,AWT的框架类、面板类、按钮类和菜单类,被命名为Frame、Panel、Button和Menu,而Swing对应的组件类被命名为JFrame、JPanel、JButton和JMenu。与AWT组件相比,Swing组件的名前多一个 “J” 字母。 另外,AWT 组件在java.awt包中,而Swing组件在javax.swing包中。

7 3.一个Java GUI简单程序 【例9.1】课本P188 Java Swing GUI应用程序中的基本代码如下: (1)引入合适的包和类
一般的Swing GUI应用程序应包含程序中的前三个引入语句,它们分别表示引入awt包、awt事件处理包和swing包。其他包按需引入。 由于Swing组件使用AWT的结构,包括AWT的事件驱动模式,所以,使用swing组件的程序一般需要使用awt包。 (2)使用缺省的观感或设置自己的观感(Look and Feel) (3)设置一个顶层的容器 (4)根据需要,使用缺省的布局管理器或设置另外的布局管理器 (5)定义组件并将它们添加到容器 (6)对组件或事件编码

8 1.容器(Container)和组件(Component)
9.1.2 容器、组件、布局和观感 1.容器(Container)和组件(Component) 一个Java的图形用户界面的最基本元素是组件,组件是可以以图形化的方式显示在屏幕上并能与用户进行交互的对象,如一个按钮、一个文本框等。 容器实际上是一种具有容纳其他组件和容器的功能的组件。抽象类Container是所有容器的父类,其中包含了很多有关容器的功能和方法。而类Container又是Java语言的组件类Component的子类。

9 2.布局管理器(Layout Manager)
为了使得图形用户界面具有良好的平台无关性,在Java语言中提供了布局管理器这个工具来管理组件在容器中的布局,而不使用直接设置组件位置和大小的方式。容器中的组件定位由布局管理器决定。每个容器都有一个缺省的布局管理器,当容器需要对某个组件进行定位或判断其大小尺寸时,就会调用其相应的布局管理器。但也可以不用缺省的布局管理器,在程序中指定其新的布局管理器。 Java平台提供多种布局管理器,常用的有FlowLayout、BorderLayout、 GridLayout、CardLayout、BoxLayout和GridBagLayout等。使用不同的布局管理器,组件在容器上的位置和大小都是很不一样的。

10 在程序中安排组件的位置和大小时,应该注意:
(1)容器中的布局管理器负责各个组件的大小和位置。因此用户无法在这种情况下直接设置这些属性。若试图使用Java语言提供的setLocation()、setSize()、setBounds()等方法,则都会被布局管理器覆盖。 (2)若用户确实需要亲自设置组件的位置和大小,则应取消该容器的布局管理器,方法为: setLayout(null); 随后,用户必须使用setLocation()、setSize()、setBounds()等方法为组件设置大小和位置,但这种方法将会导致程序的系统相关。 在一个GUI应用程序的界面上,除了可以见到上述的标准GUI元素外,还可以见到一些非交互的起到装饰、美化界面的作用的几何图形、图案、图像等内容。

11 3.观感(Look and Feel) Java swing的一个重要特征是它的可插入的“观感”体系。一个Swing应用程序或一个最终用户可指明所需要的观感,使得Swing应用程序的外观和行为都可以被定制。Swing运行一个缺省的Java观感(也称为Metal观感),还实现了模仿Motif和Windows的观感。这样,一个Swing程序可拥有Java程序的独特外观,也可以拥有熟悉的Windows操作系统外观。 在本章稍后部分的单选按钮的程序例中分别显示了Windows、Motif和Metal三种不同风格的观感。 一般在应用程序的JFrame的构造方法中或在JApplet的init()方法中进行观感的设置。

12 9.1.3事件处理(重要) 在一个GUI程序中,为了能够接收用户的输入、命令的按键和鼠标操作,程序系统首先应该能够识别这些操作并做出相应的响应。通常一个键盘和鼠标操作将引发一个系统预先定义好的事件,用户程序只要编写代码定义每个事件发生时程序应做出何种响应即可。这些代码会在它们对应的事件发生时由系统自动调用,这就是GUI程序中事件和事件响应的基本原理。 如果用户通过用户界面执行了一个动作,这将导致一个事件的发生。事件是描述用户所执行操作的数据对象。在Java中,定义了各种不同类型的事件类,用来描述各种类型的用户操作。

13 事件是由事件源产生的,事件的产生者称为事件源。例如,在Button组件上点击鼠标会产生以这个Button为源的一个事件:ActionEvent。
事件的行为多种多样,由不同的事件监听器处理,编写事件处理程序首先应确定关注的事件属于何种监听器类型,确定后对该监听器进行注册.当事件源产生了一个事件以后,该事件就委托给已经注册的事件监听器,事件监听器监听到事件后,负责执行相应的响应方法。 一个事件监听器是一个实现了给定接口的类的实例,接口中定义了相应的响应方法。

14 在AWT中,提供11种标准的监听器类型,见下表。
监听器 适配器类 注册方法 ActionListener addActionListener AdjustmentListener addAdjustmentListener ComponentListener ComponentAdapter addComponentListener ContainerListener ContainerAdapter addContainerListener FocusListener FocusAdapter addFocusListener ItemListener addItemListener KeyListener KeyAdapter addKeyListener MouseListener MouseAdapter addMouseListener MouseMotionListener MouseMotionAdapter addMouseMotionListener TextListener addTextListener WindowListener WindowAdapter addWindowListener

15 在确定监听器类型后,要用事件源类的注册方法来注册一个监听器类的对象。这样,事件源产生的事件会传送给已注册的处理该类事件的监听器对象,该对象将自动调用相应的事件处理方法来处理该事件。
具体的注册方法是:用监听器类的对象作为参数调用事件源本身的addXxxListener()方法。该方法的参数是一个监听器类的对象,有多种形式。例如: (1)分离的监听器类,该类通常为继承相应事件适配器类的子类,类中包含了事件处理方法。参数是该类的一个对象。参见例 (2)实现监听器接口,参数为this,表示本对象就是一个监听器类的对象。在本类中包含事件处理方法。如课本例9.1 (3)有名内部类,参数形式为继承事件适配器类的子类对象,在子类中包含事件处理方法。 (4)匿名内部类,参数形式为用new开始的一个无名的类定义。其中包含事件处理方法。

16 我们可以通过以下方法来注册事件监听器对象:
eventSourceObject.addEventListener(eventListenerObject); 以按钮类为例: MyActionListener listener = ; Button btn = new Button(“提交”); btn.addActionListener(listener); 事件监听器对象listener所属的类MyActionListener必须实现相应的接口,以响应事件: public class MyActionListener implements ActionListener { ...... public void actionPerformed(ActionEvent evt) //相应的响应操作 }

17 9.2 布局管理器 在容器中所有组件的布局(位置和大小)由布局管理器来控制。在Java语言中提供了FlowLayout、BorderLayout、GridLayout、CardLayout和GridBagLayout等多种布局管理器。 每种容器都有自己缺省的布局管理器。缺省地,JPanel使用FlowLayout,而内容窗格 ContentPane (JApplet、JDialog和JFrame对象的主容器) 使用BorderLayout。如果不希望使用缺省的布局管理器,则可使用所有容器的父类Container的setLayout()方法来改变缺省的布局管理器。

18 1.FlowLayout FlowLayout布局是一种最基本的布局。这种布局指的是把组件一个接一个从左至右、从上至下地依次放在容器上,每一行中的组件缺省为居中对齐。当容器的尺寸改变后,组件的大小不变,但布局将会随之变化。 FlowLayout是Applet和JPanel的缺省布局管理器。FlowLayout类的构造方法如下: FlowLayout() 创建每行组件对齐方式为居中对齐、组件间距为5个像素单位的对象 FlowLayout(int align) 创建指定每行组件对齐方式、组件间距为5个像素单位的对象,align可取三个静态常量LEFT、CENTER和RIGHT之一(分别表示左、中、右对齐方式)。

19 FlowLayout(int align, int hgap, int vgap) 创建指定每行组件对齐方式的对象,该对象也使用参数vgap和hgap指定了组件间的以像素为单位的纵横间距。
向使用FlowLayout布局的容器添加组件可简单地使用下面的语句: add(组件名); 例:import java.awt.*; public class MyFlowLayout{ public static void main(String[] args){ Frame f=new Frame(); f.setLayout(new FlowLayout()); Button b1=new Button("Fisrt"); Button b2=new Button("Seconed"); Button b3=new Button("Third"); f.add(b1);f.add(b2);f.add(b3); f.setSize(300,100);f.setVisible(true); }

20 2.BorderLayout BorderLayout 是内容窗格的缺省布局管理器。内容窗格是框架JFrame,小程序JApplet和对话框JDialog的主容器。BorderLayout将容器的布局分为五个区:北区、南区、东区、西区和中区。这几个区的分布规律是“上北下南,左西右东”。当容器的大小改变时,容器中的各个组件相对位置不变,其中间部分组件的尺寸会发生变化,四周组件宽度固定不变。

21 BorderLayout类的构造方法如下:
BorderLayout() 创建组件间无间距的BorderLayout对象。 BorderLayout(int hgap, int vgap) 创建有指定组件间距的对象。 向BorderLayout布局的容器添加组件时,每添加一个组件都应指明该组件加在哪个区域中。add()方法的第二个参数指明加入的区域,区域东南西北中可用五个静态常量表示:BorderLayout.EAST、BorderLayout.SOUTH、BorderLayout.WEST、BorderLayout.NORTH和BorderLayout.CENTER。

22 【例9.3】将五个按钮加入BorderLayout的五个区。
import java.awt.*; import javax.swing.*; public class BorderLayoutDemo extends JApplet { public void init() { Container c = getContentPane(); c.add(new Button("北North"), BorderLayout.NORTH); c.add(new Button("南South"), BorderLayout.SOUTH); c.add(new Button("东East"), BorderLayout.EAST); c.add(new Button("西West"), BorderLayout.WEST); c.add(new Button("中Center"), BorderLayout.CENTER); } 程序运行的结果见下图。

23

24 3.GridLayout GridLayout布局是将容器的空间分成若干行和列的一个个网格,可以给出网格的行数和列数,组件添加到这些网格中。当改变容器的大小后,其中的组件相对位置不变,但大小改变。容器中各个组件同高度、同宽度。各个组件缺省的排列方式为:从上到下,从左到右。 GridLayout类的构造方法如下: public GridLayout()创建单行每个组件一列的GridLayout对象。 public GridLayout(int rows, int cols) 创建指定行列数的GridLayout对象。 public GridLayout(int rows, int cols, int hgap, int vgap)创建指定行列数的GridLayout对象。

25 因为没有容器缺省使用GridLayout,因此在使用GridLayout前,要用setLayout()方法将容器的布局管理器设置为GridLayout。
在向GridLayout添加组件时,组件加入容器要按序进行,每个网格中都必须加入组件,若希望某个网格为空,可以为该网格加入一个空的标签:add(new JLabel())。

26 import java.awt.*; import java.applet.*; public class Calc extends Applet { Button button0= new Button("0"); Button button1= new Button("1"); Button button2= new Button("2"); Button button3= new Button("3"); Button button4= new Button("4"); Button button5= new Button("5"); Button button6= new Button("6"); Button button7= new Button("7"); Button button8= new Button("8"); Button button9= new Button("9"); Button buttonAdd= new Button("+"); Button buttonSubtract= new Button("-"); Button buttonMultiply= new Button("*"); Button buttonDivide= new Button("/"); Button buttonEqual= new Button("="); TextField textField = new TextField();

27 public void init() { setLayout(new GridLayout(4,2,10,10)); add(textField); add(button7); add(button8); add(button9); add(buttonEqual); add(button4); add(button5); add(button6); add(button0); add(button1); add(button2); add(button3); add(buttonAdd); add(buttonSubtract); add(buttonMultiply); add(buttonDivide); }

28 【例9.4】GridLayout布局。 import java.awt.*; import javax.swing.*;
public class GridLayoutDemo extends JApplet { public void init() { Container c = getContentPane(); c.setLayout(new GridLayout(3,2)); c.add(new Button("1")); c.add(new Button("2")); c.add(new Button("3")); c.add(new Button("4")); c.add(new Button("5")); c.add(new Button("6")); }

29 例9.4运行的结果如下图所示。

30 4.CardLayout CardLayout布局管理器能够使得多个组件共享同一显示空间,这些组件之间的关系像一叠重叠的扑克牌,只有最上面的组件是可见的。注意:在一个显示空间(卡片)中只能显示一个组件,因此,可使用容器嵌套的方法来显示多个组件。 CardLayout类的构造方法如下: CardLayout()创建间距为零的对象。 CardLayout(int hgap, int vgap)创建带有水平hgap和垂直vgap间距的对象。 为了使用叠在下面的组件,可以为每个组件取一名字,名字在用add()方法向容器添加组件时指定,需要某个组件时通过show()方法指定该组件的名字来选取它。也可以顺序使用这些组件,或直接指明选取第一个组件(用first()方法)或最后一个组件(用last()方法)。

31 【例9.5】CardLayout布局。 import java.awt.*; import javax.swing.*;
public class CardLayoutDemo extends JApplet{ CardLayout cl =new CardLayout(20,40); // 组件在卡片中有边界 JButton b1=new JButton("卡片一"); JButton b2=new JButton("卡片二"); JButton b3=new JButton("卡片三"); public void init(){ getContentPane().setLayout(cl); getContentPane().add("card1",b1); getContentPane().add("card2",b2); getContentPane().add("card3",b3); }

32 程序运行结果如下图所示。程序中的三个按钮组件顺序添加到卡片布局管理器的各个卡片上,它们共享同一显示区域,因此只能见到最上面的“卡片一”按钮。

33 5.GridBagLayout GridBagLayout是最复杂也最灵活的布局管理器。这个布局管理器将组件放入单元格中,但允许一些组件跨越单元格。 可用GridBagLayout类的构造方法GridBagLayout()来创建一个GridBagLayout布局管理器。因GridBagLayout布局设置比较复杂,这里就不介绍了,请读者参看API说明或其他资料。

34 6.自定义布局 若希望按照自己的要求来进行组件和界面图形元素的布局,可用容器的setLayout(null)方法将容器的布局管理器设置为空,然后用下面的方法设置组件在容器中的位置和大小: setBounds(int a,int b,int width,int height) 其中,参数a和b指定矩形形状的组件左上角在容器中的坐标,width和height指定组件的宽和高。 【例9.6】设置自己的布局管理器。 import java.awt.*; import javax.swing.*; class NullLayout extends JFrame{

35 NullLayout(){ super("建设自己的布局管理器"); Container c=getContentPane(); // 也可不用内容窗格 c.setLayout(null); JButton jb1 =new JButton("按钮1"); JButton jb2 =new JButton("按钮2"); c.add(jb1);c.add(jb2); jb1.setBounds(10,10,100,30); jb2.setBounds(10,50,100,30); } public static void main(String args[]){ NullLayout nl=new NullLayout(); nl.setSize(200,150); nl.setVisible(true);

36 程序的运行结果如下图所示。注意,采用这种方式的布局,组件的位置和大小将不随窗口大小的变化而变化。
下图为例9.6的运行界面。

37 补 : 创建简单的GUI应用程序 1.创建窗口 在软件项目编程中,和用户建立接口的首先是一个特殊的窗口中,这个窗口是一个特殊的容器,在这个容器中可以容纳其他的可视化组件(Component),或者是另外的容器,而这些组件之间又进行着有机的整合和联系,最终构成一个良好的可视化接口。 这个特殊的窗口可以是一个简单的窗口(Window或JWindow类),但是它没有提供标题栏,也没有提供最大化和最小化以及关闭按钮,同时也没有在图形化接口操作系统中所看见的大多数窗口所具有的其他功能.另外这个特殊的窗口也可以是一个框架,而它有标题栏、窗口管理按钮、状态区以及其他窗口功能。所以一般的创建窗口程序的首要任务是创建一个继承Frame(或JFrame)类的子类,并用它作为特殊窗口来容纳其他容器或组件。

38 首先声明一个MyFrame类来继承JFrame,代码如下: public class MyFrame extends Frame{
//代码…… } 因为用到了Frame类,所以要引用该类所在的包。 因为继承了Frame类,所以MyFrame类中基本上已经完成了一个框架的创建,剩下的任务就是对这个框架进行一定的修饰,如调用超类的构造方法进行初始设置的设定,确定框架应该显示的位置和大小,决定用户如何关闭框架、显示框架等。超类Frame有两个构造方法,Frame()和Frame(String name).后者参数设定了标题栏,如果选用无参的构造方法,则标题栏的设定可以用setTitle(String Name)方法实现。如在MyFrame构造方法中有: super(); this.setTitle(“框架”);//其中this可以省略

39 框架大小和位置的显示也可以用一个方法完成:
框架的显示位置的设定: setLocation(Point p) 其中p是Java.awt.Point类的一个对象,如: setLocation(new Point(100,100)); 框架大小的显示: setSize(int width,int height) 框架大小和位置的显示也可以用一个方法完成: setBounds(100,100,400,200) 是指框架从(100,100)画到点(400,200)处

40 框架层次关系 Object Component Container Window Frame

41 Component类是所有GUI对象的祖先,Window类是Frame类的父类。对于框架外观的操作比较重要的方法如下:
setTitle——设置窗口中标题栏的文字。 setResizable——设置用户是否可以改变框架大小。 dispose方法——关闭窗口,并回收该窗口的所有资源。 setSize——设置组件的大小。 setBackground——设置组件的背景颜色。 setVisible——设置组件是否可见。 setBounds——重新设置组件的大小和位置。

42 2.执行程序 在完成了基本的创建一个在指定位置显示指定大小的并且有指定标题的框架之后,接下来要执行并显示它,而这一步骤需要编写一个main()方法,在main()方法中创建已编写好的MyFrame类的对象mf。一个框架在创建的同时缺省为这个框架是可视的,否则调用对象的setVisible()方法,同时这个方法也可以在MyFrame类的构造方法中实现。如setVisible(true). 3.退出程序 为了退出程序,关闭显示结果,Java程序允许用户单击框架的“关闭”按钮来关闭,这需要对当前生成的窗口进行监视,监视用户操作需要使用事件处理类,实现WindowListener接口可以实现这一操作,WindowListener接口定义了以下7个方法来实现窗口的相应的操作:

43 windowActivated():当窗口成为活动窗口时响应此方法,这意味着这个接口可以接收来自键盘的响应。
windowDeactivated():窗口变为非活动的,不能接收键盘的响应。 windowClosing():窗口正在关闭 windowClosed():窗口已经关闭 windowOpened():窗口可见 windowIconified():窗口已经最小化 windowDeiconified():窗口已经最大化

44 定义一个类来实现WindowListener接口,在感兴趣的方法中添加我们需要的代码,然后让其他方法为空即可。
class QuitWindow implements WindowListener { public void windowClosing(WindowEvent evt) System.exit(0); } void windowOpened(WindowEvent evt) {} void windowClosed(WindowEvent evt) {} void windowIconified(WindowEvent evt) {} void windowDeiconified(WindowEvent evt) {} void windowActivated(WindowEvent evt) {} void windowDeactivated(WindowEvent evt) {}

45 java.awt.event包中的另外一个类WindowAdapter实现了有7个空方法的这个接口,但没有任何操作,通过创建WindowAdapter类的子类,可以重载希望处理的和用户操作事件相关的方法。下面给出用WindowAdatper类的子类ExitFrameg来实现框架程序的关闭。 Import java.awt.event.*; Class ExitFrame extends WindowsAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); } ExitFrame类国为继承了WindowAdapter类,所以实现了WindowListener接口,这样ExitFrame类的对象就可以用于监视框架,而这个类只有一个任务,就是等待关闭窗口。System.exit(0)的功能是关闭正在运行的程序。如果程序因为某些错误关闭,则参数是其他整型值。

46 可以看到新编写的ExitFrame类还没有和框架程序类MyFrame建立联系,也就是说没有把事件监听器注册到框架中,可以通过在ExitFrame类的构造方法中调用addWindowListener()方法来建立联系: ExitFrame ef=new ExitFrame(); this.addWindowListener(ef); 通过上面的介绍,就完成了窗口的建立、执行程序和退出程序的操作。 创建一个空框架的完整代码如下:

47 例:显示一个空框架 import java.awt.*; import java.awt.event.*;
public class MyFrame extends Frame { public MyFrame(String str) super(str); addWindowListener(new ExitFrame()); setSize(300,200); setBackground(Color.yellow); setVisible(true); } public static void main(String[] args) MyFrame mf=newMyFrame("My FirstFrame");

48 class ExitFrame extends WindowAdapter
{ public void windowClosing(WindowEvent evt) Frame frm=(Frame)evt.getSource(); frm.setVisible(false); frm.dispose(); System.exit(0); }

49 设置具有以下特征的框架:它的高度和宽度为整个屏幕的1/3;自定义窗口的标题和背景;窗口的大小不可变。
例: 框架外观的设置 设置具有以下特征的框架:它的高度和宽度为整个屏幕的1/3;自定义窗口的标题和背景;窗口的大小不可变。 import java.awt.*; import java.awt.event.*; public class FrameSizeSet extends Frame { public FrameSizeSet() addWindowListener(new Wadapt()); setTitle("框架外观"); //设置标题 setBackground(Color.yellow); //设置背景 Toolkit tk=Toolkit.getDefaultToolkit(); //获得屏幕的相关尺寸 Dimension screenSize=tk.getScreenSize(); int screenHeight=screenSize.height; int screenWidth=screenSize.width; //设置框架的尺寸,大小不可调 setSize(screenWidth/3,screenHeight/3); setResizable(false); setVisible(true); }

50 public static void main(String[] args)
{ FrameSizeSet frm=new FrameSizeSet(); } class Wadapt extends WindowAdapter public void windowClosing(WindowEvent evt) Frame frm=(Frame)evt.getSource(); frm.setVisible(false); frm.dispose(); System.exit(0);

51 向框架中添加其它组件(awt) 1.文本编辑区
文本编辑区(TextField或TextArea),可以接受用户的文本输入,并有一定的编辑功能,如退格,块复制,块粘贴等。 TextField类提供了多种构造方法: public TextField() public TextField(int columns):指定能容纳字符的个数 Public TextField(String text):指定初始化文本 Public TextField(String text,int columns)

52 创建TextArea的方法与TextField的方法相似,除了在指定文本区大小时既要指定文本区的列数又要给出文本区的行数外,其它是完全相同的,构造方法:
public TextArea() public TextField(int rows,int columns):指定能容纳字符的个数 Public TextField(String text):指定初始化文本 Public TextField(String text,int rows,int columns)

53 如: TextField textField = new TextField("我是TextField类文本框!",60);
TextArea textArea = new TextArea("我是TextArea类文本框!"); add(textField); add(textArea);

54 TextField类中的常用方法: TextArea类中常用方法 Public int getColumns()
Public String getText() Public void setText(String t) TextArea类中常用方法 Public void append(String str) Public void insert(String str,int pos) Public setRows(int rows) Public setColumns(int cols)

55 文本框和文本区的事件响应 文本框除了继承它们父类的事件类型,如TextEvent,KeyEvent,MouseEvent等外,还可以产生一个ActionEvent事件,当向文本框中键入信息并按下Enter键后,就会发生该事件。为了响应该事件,必须实现相应的监听器接口ActionListener,并为文本框注册监听器,然后通过对ActionListener接口中的actionPerformed()方法的实现来完成对事件的处理。 文本区与文本框相同的是可以接收继承你类的多种事件,但由于它是多行的,所以按Enter键不会产生事件,此时可以在文本区旁边设置一个按钮,通过按钮的单击事件来完成相应的操作。 当文本区的内容发生改变时会产生相应的TextEvent事件,相应的事件监听器为TextListener,通过addTextListener()方法注册,当文本区内容改变时,会调用监听器接口中相应的方法textValueChanged(TextEvent e)来处理。

56 例:创建一个文本框和文本区,当文本框中发生ActionEvent事件时,把非空的文本框内容换行追加到文本区中,然后清空文本框
import java.awt.*; import java.awt.event.*; public class MyText implements ActionListener{ static TextField text1; static TextArea text2; public static void main(String args[]){ Frame f=new Frame(); text1=new TextField("",20); text2=new TextArea("",4,30); f.add(text1); f.add(text2); text1.addActionListener(new MyText()); f.setLayout(new FlowLayout()); f.setBounds(0,0,300,150); f.setVisible(true); }

57 public void actionPerformed(ActionEvent e){
if(!(text1.getText().equals(""))) {text2.append(text1.getText()+”\n”); text1.setText(""); }

58 稍作修改 import java.awt.*; import java.awt.event.*; public class MyText extends Frame implements ActionListener{ static TextField text1; static TextArea text2; public MyText(){ super("文本框示例"); text1=new TextField("",20); text2=new TextArea("",4,30); add(text1); add(text2); text1.addActionListener(this); this.setLayout(new FlowLayout()); setBounds(0,0,300,150); setVisible(true); } public static void main(String args[]){ MyText my=new MyText(); public void actionPerformed(ActionEvent e){ if(!(text1.getText().equals(""))) {text2.append(text1.getText()); text1.setText("");

59 2.复选框 有“选中”和“未选中”两种状态,任何时候都只能处于这两种状态之一,支持二选一的操作。不同的Checkbox对象之间不排斥,允许用户选中任意多个Checkbox对象。创建复选框的构造方法有: public Checkbox():创建不带标签的复选框 public Checkbox(String label):创建带标签的复选框 public Checkbox(String label,boolean state):创建带标签的复选框且指定选择状态,true表示选中,false表示未选中 如: Checkbox checkbox1 = new Checkbox("北京"); Checkbox checkbox2 = new Checkbox("上海"); add(checkbox1); add(checkbox2);

60 在对复选框对象操作时,常用的方法有: 复选框的事件响应: public String getLabel()
public void setLabel(String label) public boolean getState() public void setState(boolean state) 复选框的事件响应: 复选框类响应的主要事件是项目事件,即ItemEvent事件,单击复选框就是发生ItemEvent事件,ItemEvent事件对应的监听接口是ItemListener,在接口中只有一个方法 itemStateChanged(ItemEvent e). 在有多个事件源时,正确判断事件源的方法是EventObject类中的getSource(),也可以用ItemEvent类中的getItem()方法得到复选框的标签字符串来确定事件源 确定事件源后,可以用getState()方法来判断当前事件源对象表示的选择状态,从而设计相应的功能代码

61 3.单选按钮 单选按钮(CheckboxGroup),是一组Checkbox的集合,每个Checkbox对象对应着一种可能的取值情况,即对应一个选项。CheckboxGroup支持用户“多选一”的输入,按钮之间是互斥的(即如果一个被选中,其它都无法选中)。 CheckboxGroup类提供了一个方法来创建复选按钮组, Public CheckboxGroup() CheckboxGroup类提供的用来管理复选按钮组的常用方法有: Public Checkbox getSelectedCheckbox():得到当前选中的复选按钮 Public void setSelectedCheckbox(Checkbox box):设置被选中的复选按钮对象

62 创建单选按钮的方法有: Public Checkbox(String label,boolean state,CheckboxGroup group) Public Checkbox(String label, CheckboxGroup group,booean state) 其中,label是单选按钮的标签名,该按钮属于复选按钮组group,state是初始时按钮的状态,最后一个被加入的状态为true的复选按钮对象在复选按钮组显示时被默认选 中。 要把一个复选按钮对象加入复选框组对象中,既可以在创建复选按钮时加入,也可以用setCheckboxGroup(CheckboxGroup g)方法实现

63 如: CheckboxGroup checkboxGroup = new CheckboxGroup();
Checkbox checkbox3 = new Checkbox("是"); Checkbox checkbox4 = new Checkbox("否"); add(checkbox3); add(checkbox4); checkbox3.setCheckboxGroup(checkboxGroup); checkbox4.setCheckboxGroup(checkboxGroup);

64 单选按钮的事件响应 单选按钮的事件响应同复选框,单击时,相应的项目事件被调用,在事件处理方法itemStateChanged(ItemEvent e)中,利用ItemEvent类的getSource()方法返回所选择的单选按钮的对象名

65 程序举例:单复选按钮的实现 import java.awt.*; import java.awt.event.*; public class MyCheck implements ItemListener{ static TextField text1; static Checkbox check1; static Checkbox check2; static Checkbox check3; public static void main(String args[]){ Frame f=new Frame("Hello"); text1=new TextField("Please control me",20); check1=new Checkbox("BOLD"); CheckboxGroup group=new CheckboxGroup(); check2=new Checkbox("blue",group,false); check3=new Checkbox("red",group,false); f.setLayout(new FlowLayout());

66 f.add(text1); f.add(check1); f.add(check2); f.add(check3); check1.addItemListener(new MyCheck()); check2.addItemListener(new MyCheck()); check3.addItemListener(new MyCheck()); text1.setFont(new Font("宋体",Font.PLAIN,15)); f.setBounds(0,0,200,100); f.setVisible(true); }

67 public void itemStateChanged(ItemEvent e){
if(e.getSource()==check1) if(e.getStateChange()==1) text1.setFont(new Font("宋体",Font.BOLD,15)); else text1.setFont(new Font("宋体",Font.PLAIN,15)); if(e.getSource()==check2) text1.setForeground(Color.blue); text1.setForeground(Color.red); }

68 4.按钮 按钮(Button),可以在按钮上显示文本;往往对应着某个特定的操作或者功能,当用户点击按钮时就执行这个预定义好的操作或者功能。
创建按钮对象的构造方法如下: public Button() public Button(String label); 当一个按钮被创建后,需要把按钮加进容器中如: Button button = new Button("我是按钮!"); add(button);

69 Button类常用的方法: 按钮的事件响应:
public String getLabel() public void setLabel(String label) 按钮的事件响应: ActionEvent事件,监 听器接口ActionEventListener,方法actionPerformed().注册监听器使用方法 addActionListener(ActionEvent e) 当有多个按钮被监 听器监听,可以用getActionCommand()方法区分事件源

70 举例:实现使用按钮控制窗体背景色的功能 import java.awt.*; import java.awt.event.*; public class MyButton extends Frame { Button b1=new Button("red"); Button b2=new Button("yellow"); public MyButton(){ super("按钮示例"); this.setLayout(new FlowLayout()); b1.setActionCommand("red") ; b1.addActionListener(new ButtonCtl()); b2.setActionCommand("yellow"); b2.addActionListener(new ButtonCtl()); this.addWindowListener(new Wadapt()); add(b1); add(b2); setBounds(0,0,300,150); setVisible(true); } public static void main(String args[]){ MyButton my=new MyButton(); }}

71 class ButtonCtl implements ActionListener{
public void actionPerformed(ActionEvent e){ MyButton mb=new MyButton(); if(e.getActionCommand()=="red") mb.setBackground(Color.red); else if(e.getActionCommand()=="yellow") mb.setBackground(Color.yellow); } class Wadapt extends WindowAdapter { public void windowClosing(WindowEvent evt) Frame frm=(Frame)evt.getSource(); frm.setVisible(false); frm.dispose(); System.exit(0);

72 5.标签 标签(Label),可以显示信息,不能接受输入。一般用作程序动态指定说明性信息。Label类提供的构造方法如下:
public Label() public Label(String text) public Label(String text,int alignment) Alignment的取值有三个:Label.CENTER,Label.LEFT,Label.RIGHT,分别对应整数值0,1,2 如: Label label = new Label("我是标签!“, Label.RIGHT); add(label);

73 Label类提供的常用方法: 对标签一般不作事件处理 public String getText()
public void setAlignment(int alignment) public void setText(String text) 对标签一般不作事件处理

74 6.列表 列表(List),列出若干选项供用户进行“多选多”的操作,创建列表时要把各项内容添加进去。List构造函数: 常用方法:
List(int rows) 创建一个用指定可视行数初始化的新滚动列表。 List(int rows, boolean multipleMode)          创建一个初始化为显示指定行数的新滚动列表。 常用方法: add(String item)       向滚动列表的末尾添加指定的项。  String getItem(int index)  获取与指定索引关联的项。 int getItemCount()  获取列表中的项数。  void remove(int position)   从此滚动列表中移除指定位置处的项。  voidremoveAll()          从此列表中移除所有项。

75 如: List对事件的响应: List list = new List(4,true); add(list);
list.add("中国"); list.add("德国"); list.add("新加坡"); List对事件的响应: 当用户单击列表中的可选项时,将引发ItemEvent事件,该事件需要由ItemListener接口中的itemStateChanged()方法处理。当用户双击列表中的可选项时,将引发ActionEvent事件,该事件需要由ActionListener接口中的actionPerformed()方法进行处理。

76 7.下拉列表 下拉列表(Choice),列出若干选项供用户进行“多选一”的操作。下拉列表中除了被选中的选项,其它的都隐藏起来。单击下拉列表右侧的下三角按钮,就可以看到其它的选项。构造方法: Choice() 创建一个新的选择菜单。 创建下拉列表时也要把各项内容添加进去。可用add()方法实现,例如: Choice choice = new Choice(); add(choice); choice.add("男"); choice.add("女");

77 与列表框类似,用户对下拉列表框的操作将引发ItemEvent事件,该事件需要由实现了ItemListener接口的类进行处理。

78 8. 菜单组件 典型的菜单: 菜单 菜单项 快捷键 菜单栏 子菜单 被禁用 复选框菜单项 被启用 弹出式菜单

79 创建菜单 四个步骤:创建菜单栏;创建菜单以及子菜单;创建菜单项;将菜单项加入到子菜单或菜单中,将子菜单加入到菜单中,将菜单加入到菜单栏中。 (a)创建菜单栏,并将菜单栏加入到框架中。 MenuBar menuBar = new MenuBar(); setMenuBar(menuBar); 如: Frame fr=new Frame(“Menubar”); MenueBar mb=new MenuBar(); fr.setMenuBar(mb);fr.setSize(150,100);fr.setVisible(true); 菜单条不支持监听器,因为在其中所发生的各类事件由菜单项处理

80 (b)创建“File”菜单、“Edit”菜单和“View”菜单。
Menu fileMenu = new Menu("File"); Menu editMenu = new Menu("Edit"); Menu viewMenu = new Menu("View"); (b)创建子菜单。 Menu optionMenu = new Menu("Option"); (c)创建“New”菜单项,并添加快捷键和事件监听器 MenuItem newItem = new MenuItem("New", new MenuShortcut('N')); newItem.addActionListener(this);

81 (d)将菜单项加入到子菜单或菜单中,将子菜单加入到菜单中,将菜单加入到菜单栏中。
fileMenu.add(newItem); editMenu.add(pasteItem); viewMenu.add(optionMenu); menuBar.add(fileMenu); menuBar.add(editMenu); menuBar.add(viewMenu);

82 创建带复选项的菜单项 带复选项的菜单项是一种特殊的菜单项,在该菜单项的前面有一个复选项,可以对它进行选中或不选中的操作。 当菜单项的复选状态发生改变时,会引发ItemEvent事件,可以使用ItemListener接口中的itemStateChanged()方法对此事件进行响应。 /*创建带复选项的菜单项“ToolBar”,注册事件监听器 并加入到子菜单optionMenu中*/ CheckboxMenuItem toolItem; toolItem = new CheckboxMenuItem("ToolBar"); toolItem.addItemListener(this); optionMenu.add(toolItem);

83 菜单项的使用状态 菜单项是否能被选取取决于菜单项的启用和禁用状态。 //初始设置“Save”菜单项为禁用状态 saveItem.setEnabled(false); 快捷键 快捷键可使得用户通过键盘进行菜单选择,显示为菜单项旁边的组合键。 //设置“Exit”菜单项的快捷键为“Ctrl+T” exitItem = new MenuItem("Exit",new MenuShortcut('T')); 分割线的设置: 用户可以在菜单的各菜单项之间添加分割线,方法是:addSeparator()

84 弹出式菜单 弹出式菜单的创建和一般菜单的创建基本相同,也需要新建一个弹出式菜单后再加入菜单项。 //创建弹出式菜单 popup = new PopupMenu(); /*新建弹出式菜单中的“Cut”菜单项,并添加快捷键和 事件监听器*/ cutItemPop = new MenuItem("Cut", new MenuShortcut('C')); cutItemPop.addActionListener(this); 注意:弹出式菜单缺省是不可见的,因此必须显式调用show()方法。该方法的原型定义为: public void show(Component origin, int x, int y) 在该方法中需要用一个组件作参数,该组件应该存在于弹出式菜单所依附的组件中。也就是说,弹出式菜单可以被其拥有者的包容体系内的任何组件触发。

85 【例7.22】菜单示例 菜单的用法。 程序代码见MenuExample.java。运行结果如下:

86 9.3常用Swing组件 9.3.1 容器组件 1.JFrame框架
框架,是JFrame类的对象,是swing GUI应用程序的主窗口。窗口有边界、标题、关闭按钮等。对Java应用程序,应至少包含一个框架,例9.1的应用程序即使用了框架。有时,小程序也使用框架。JFrame类继承于Frame类。JFrame类的构造方法如下: JFrame() 创建无标题的初始不可见框架。 JFrame(String title) 创建标题为title的初始不可见框架。

87 要显示框架对象代表的框架窗口,可使用方法setVisible()。可用语句:
例如: JFrame frame = new JFrame("Java GUI应用程序"); 要显示框架对象代表的框架窗口,可使用方法setVisible()。可用语句: frame.setVisible(true); 可使得JFrame类对象frame表示的框架窗口显示到屏幕上。一般在显示框架前,可设置框架的初始显示大小可使用setSize()方法或pack()方法。例如: frame.setSize(200,150); // 设置框架窗口初始大小为200×150点 frame.pack(); // 设置框架窗口初始大小为刚好只显示出所有的组件。

88 向JFrame添加组件的方法与AWT不同,JFrame内含JRootPane容器组件,而JRootPane又内含contentPane容器组件,我们常用的组件就包含在contentPane容器组件中,而不是直接含于JFrame中,因此,在添加组件时,并不直接添加组件到框架,而是添加到内容窗格(contentPane),改变其他特性(布局管理器、背景色等)也对内容窗格进行。 要存取内容窗格,可通过getContentPane()方法, 若希望用自己的容器替换掉内容窗格(例如用JPanel),可以使用setContentPane()方法。 选择框架的关闭按钮后,框架窗口将自动关闭,但若是应用单个框架的应用程序,为了在选择框架的关闭按钮时能退出程序,应添加WindowListener监听器或书写下列代码: frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); //修改前面显示空框架的例 看效果

89 JFrame的缺省观感为Java (Metal), 若要使用其他的观感,必须显式设置。JFrame(应该说是内容窗格)的缺省布局管理器是BorderLayout。

90 2. JPanel面板 JPanel是一种添加到其他容器使用的容器组件,可将组件添加到JPanel,然后再将JPanel添加到某个容器。JPanel也提供一个绘画区域,可代替AWT的画布Canvas (没有JCanvas)。 javax.swing.JPanel类继承于javax.swing.JComponent类,其构造方法有: public JPanel() 创建具有缺省FlowLayout布局的JPanel对象。 public JPanel(LayoutManager layout) 创建具有指定布局管理器的JPanel对象。

91 将JPanel作为画布的绘画区域使用时,要使用下面的两个步骤:
首先,设置画布绘图区域的大小; 其次,使用paintComponent()方法(不是paint()方法)来绘图,在该方法体中,首先调用方法super.paintComponent()来清除显示区域。 例如: public void paintComponent(Graphics g) { super.paintComponent(g); ... }

92 JPanel可指定边界,可用的边界有titled、etched、beveled 、line、matte、compound和empty等,也可以创建自己的边界。可用JComponent类的setBorder()方法设置边界。其用法如下: public void setBorder(Border border) 其中,Border类的参数可用javax.swing.BorderFactory类中的方法获得。获取各种相应边界的方法为: createTitledBorder() createEtchedBorder() createBevelBorder() createRaisedBevelBorder() createLoweredBevelBorder() createLineBorder() createMatteBorder() createCompoundBorder() createEmptyBorder()

93 【例9.7】使用JPanel。 import java.awt.*; import javax.swing.*;
class JPanelDemo extends JPanel { JButton b1 = new JButton("JPanel"); JButton b2 = new JButton("Demo"); public JPanelDemo() { setBackground(Color.white); add(b1); add(b2); }

94 public static void main(String[] args) {
JPanel jp = new JPanelDemo(); jp.setBorder( BorderFactory.createTitledBorder( "Hello,Border")); JFrame frame = new JFrame("JPanelDemo"); frame.setSize(200, 150); frame.setContentPane(jp); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }

95 例9.7程序运行结果如下图所示。

96 Applet缺省的布局管理器是FlowLayout,而JApplet(内容窗格)缺省的布局管理器是BorderLayout。
javax.swing.JApplet类是java.applet.Applet类的子类。使用Swing组件的小程序需继承JApplet类。 除了所处的java包不同外,JApplet与Applet的主要区别还有: (1)缺省的布局管理器不同 Applet缺省的布局管理器是FlowLayout,而JApplet(内容窗格)缺省的布局管理器是BorderLayout。 (2)加入组件的方式不同 Applet可直接加入组件,而JApplet缺省使用内容窗格ContentPane作为主容器。加入Swing组件时,要先使用JApplet的方法getContentPane()获得一个Container对象,再调用这个对象的add()方法将Swing组件加入到JApplet的容器中。

97 4.JTabbedPane javax. javax.swing.JTabbedPane类继承于javax.swing.JComponent,它的对象反映为一组带标签的面板,每个面板都可以存放组件,因此JTabbedPane是一容器组件。 JTabbedPane类的构造方法有: JTabbedPane() 创建空对象,该对象具有缺省的标签位置JTabbedPane.TOP和缺省的布局策略JTabbedPane.WRAP_TAB_LAYOUT。 JTabbedPane(int tabPlacement) 创建空对象,该对象具有指定的标签位置:JTabbedPane.TOP、JTabbedPane.BOTTOM、JTabbedPane.LEFT或JTabbedPane.RIGHT以及缺省的布局策略JTabbedPane.WRAP_TAB_LAYOUT。 JTabbedPane(int tabPlacement, int tabLayoutPolicy) 创建空对象,该对象具有指定的标签位置和布局策略。布局策略还有:SCROLL_TAB_LAYOUT

98 【例9.8】使用JTabbedPane容器。 import java.awt.*; import java.awt.event.*;
import javax.swing.*; import javax.swing.event.*; public class JTabbedPaneDemo{ public static void main(String args[]){ new MyTabbedPane(); } class MyTabbedPane extends JFrame implements ChangeListener,ActionListener{ JTabbedPane jt; JButton jb[]; int index = 0;

99 MyTabbedPane(){ super("使用标签面板容器"); jt = new JTabbedPane(); jb = new JButton[5]; for(int i = 0;i<5;i++){ jb[i] = new JButton("第" + i + "页面板"); jb[i].addActionListener(this); jt.addTab("页标签" + i,jb[i]); } jt.addChangeListener(this); getContentPane().add(jt,BorderLayout.CENTER); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(300,200); setVisible(true);

100 public void stateChanged(ChangeEvent e){
if(e.getSource()==jt){ int i = ((JTabbedPane)e.getSource()) .getSelectedIndex(); jb[index].setVisible(false); jb[i].setVisible(true); index = i; } public void actionPerformed(ActionEvent e){ setTitle(“响应单击” +((JButton)e.getSource()).getText());

101 例9.8运行结果如下图所示。

102 JButton类提供对按钮的支持,它的类层次关系如下:
按钮是GUI中非常重要的一种基本组件。按钮一般对应一个事先定义好的事件、执行功能、一段程序。当使用者单击按钮时,系统自动执行与该按钮联系的程序,从而完成预定的功能。 JButton类提供对按钮的支持,它的类层次关系如下: java.awt.Container └ javax.swing.JComponent └ javax.swing.AbstractButton └ javax.swing.JButton

103 JButton类有如下的构造方法: JButton() 创建空按钮。 JButton(Icon icon) 创建带图标的按钮。
JButton(String text) 创建带文字的按钮。 JButton(String text, Icon icon) 创建带文字和图标的按钮。 JButton组件与AWT的Button组件相比,增加了显示文本中可用HTML标记,可带图标等功能。 在JButton按钮的使用中,常用到继承来的setMnemonic()(设置快捷字母键)、setActionCommand()(设置动作命令)方法等。 JButton组件引发的事件为ActionEvent,可实现ActionListener监听器接口的actionPerformed()方法,用addActionListener()方法注册,用getActionCommand()或getSource()方法确定事件源。

104 【例9.9】设计一个GUI应用程序,有两个标签l1、l2和三个按钮b1,b2,b3。l1标签显示固定的文字,l2标签的文字随选择不同的按钮而变化;选择b1按钮时,l2标签显示为“欢迎进入Java世界”,选择b2按钮时,l2标签显示当前的日期,选择b3按钮时,退出该应用程序。程序如下(自己看) import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; public class JButtonDemo extends Jpanel implements ActionListener{ JButton b1,b2,b3; static JLabel l1,l2; JButtonDemo(){

105 " 这是一个演示按钮动作的程序",JLabel.CENTER); l2 = new JLabel(" ",JLabel.CENTER);
b1 = new JButton("欢迎[w]"); b1.setMnemonic(KeyEvent.VK_W);// 设置按钮的快捷键 b1.setActionCommand("welcome"); b2 = new JButton("日期[d]"); b2.setMnemonic(KeyEvent.VK_D);// 设置快捷字符为D b2.setActionCommand("date"); b3 = new JButton("退出[q]"); b3.setMnemonic(KeyEvent.VK_Q);// 设置快捷字符为Q b3.setActionCommand("quit"); b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this);

106 add(b1);add(b2);add(b3);
} public void actionPerformed(ActionEvent e){ Calendar c1 = Calendar.getInstance(); if(e.getActionCommand().equals("welcome")) l2.setText("欢迎进入Java世界。"); else if(e.getActionCommand().equals("date")) l2.setText("今天是"+c1.get(Calendar.YEAR)+ "年"+(c1.get(Calendar.MONTH)+1)+ "月" + c1.get(Calendar.DATE) + "日"); else System.exit(0); l2.setHorizontalAlignment(JLabel.CENTER); // 标签文字水平居中

107 本程序中命令按钮设置了快捷字母键,可用鼠标单击或按Alt + 快捷字母来选择按钮。
public static void main(String args[]){ JFrame frame=new JFrame("使用JButton"); frame.getContentPane().add(new JButtonDemo(),BorderLayout.SOUTH); frame.getContentPane().add(l1,BorderLayout.NORTH); frame.getContentPane().add(l2,BorderLayout.CENTER); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } 本程序中命令按钮设置了快捷字母键,可用鼠标单击或按Alt + 快捷字母来选择按钮。

108 例9.9运行启动后选择 “欢迎” 按钮和选择“日期”按钮后显示的情况见下左图和下右图。
【例9.10】带图形和HTML文字的按钮。(简单讲解) import java.awt.*; import javax.swing.*;

109 public class JButtonDemo1 extends JFrame{
public static void main(String[] args){ new JButtonDemo1( ); } public JButtonDemo1( ){ super("Using JButton"); Container content = getContentPane(); content.setBackground(Color.white); content.setLayout(new FlowLayout()); JButton button1 = new JButton( "<html><h2><font color = blue>Java"); content.add(button1); ImageIcon im = new ImageIcon( "images/newssms.gif"); JButton button2 = new JButton(im);

110 content.add(button2); JButton button3 = new JButton("Java", im); content.add(button3); JButton button4 = new JButton("Java", im); button4.setHorizontalTextPosition( SwingConstants.LEFT); content.add(button4); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); setVisible(true); }

111 程序中使用了类IconImage和指定图标图像文件名来创建图标图像对象,程序的运行结果如下图所示。

112 9.3.3 标签(JLabel) 标签是用户不能修改只能查看其内容的组件,常用来在界面上输出信息。JLabel类提供了对标签的支持,它的类层次关系为:javax.swing.JComponent - javax.swing.JLabel。 JLabel类的构造方法有: JLabel() 创建一个空标签。 JLabel(Icon image) 创建一个带指定图像的标签。 JLabel(Icon image, int horizontalAlignment) 创建一个带指定图像和水平对齐方式的标签。 JLabel(String text) 创建一个带文字的标签。 JLabel(String text, Icon icon, int horizontalAlignment) 创建一个带文字、图像和指定水平对齐方式的标签。

113 JLabel(String text, int horizontalAlignment)创建一个带文字和指定水平对齐方式的标签。
其中,horizontalAlignment水平对齐方式可以使用表示左对齐、右对齐、居中对齐的常量JLabel.LEFT、JLabel.LEFT和JLabel.CENTER。 【例9.11】具有文字对齐的标签。 import javax.swing.*; import java.awt.*; public class JLabelAlignDemo extends JApplet { public void init(){ Container c = getContentPane(); c.add(new JLabel("文字左对齐标签",JLabel.LEFT), BorderLayout.NORTH); c.add(new JLabel("文字右对齐标签",JLabel.RIGHT), BorderLayout.CENTER);

114 程序运行结果见下图。 c.add(new JLabel("文字居中标签",JLabel.CENTER),
BorderLayout.SOUTH); } 程序运行结果见下图。

115 JLabel类常用方法有: 【例9.12】使用带图标的标签。
public void setText(String text)定义这个组件将显示的单行文字。 public String getText() 返回标签显示的文字。 public Icon getIcon() 返回标签显示的图像。 public void setIcon(Icon icon)定义这个组件将显示的图标。 【例9.12】使用带图标的标签。 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class JLabelDemo extends JApplet { public void init() { Container c = getContentPane(); Icon icon = new ImageIcon("images/cup.gif");

116 程序运行结果如下图所示。 JLabel label = new JLabel(
"Swing!", icon, JLabel.CENTER); c.add(label, BorderLayout.CENTER); } 程序运行结果如下图所示。

117 9.3.4 复选框(JCheckBox) JCheckBox类的构造方法如下:
javax.swing.AbstractButton └ javax.swing.JToggleButton └ javax.swing.JCheckBox JCheckBox类的构造方法如下: JCheckBox()创建无文本的初始未选复选框按钮。 JCheckBox(Icon icon)创建有图像无文本的初始未选复选框按钮。 JCheckBox(Icon icon, boolean selected)创建带图像和选择状态但无文本的复选框按钮。

118 JCheckBox(String text)创建带文本的初始未选复选框按钮。
JCheckBox(String text, boolean selected)创建具有指定文本和状态的复选框按钮。 JCheckBox(String text, Icon icon)创建具有指定文本和图标图像的初始未选复选框按钮。 JCheckBox(String text, Icon icon, boolean selected)创建具有指定文本、图标图像、选择状态的复选框按钮。 其中,构造方法的参数selected若为真,则表示按钮初始状态为选中。 JCheckBox类常用的方法有继承来的方法isSelected()(AWT中获取状态用getState()方法),其格式为: public boolean isSelected()当复选框按钮选中时返回true,否则返回false。

119 【例9.13】选择粗体、斜体复选框按钮,改变文本框中显示文字的字形。
JCheckBox类的选择事件是ItemEvent ,可实现ItemListener监听器接口的itemStateChanged()方法来处理事件,用addItemListener()方法注册。 【例9.13】选择粗体、斜体复选框按钮,改变文本框中显示文字的字形。 import javax.swing.*; import java.awt.event.*; import java.awt.*; public class JCheckBoxDemo extends Japplet implements ItemListener{ private JTextField t; private JCheckBox bold,italic; public void init(){ t = new JTextField("观察这里文字字形的变化",40);

120 t.setFont(new Font("Serif",Font.PLAIN,20));
getContentPane().add(t,BorderLayout.NORTH); bold = new JCheckBox("粗体Bold"); bold.addItemListener(this); getContentPane().add(bold,BorderLayout.CENTER); italic = new JCheckBox("斜体Italic"); italic.addItemListener(this); getContentPane().add(italic,BorderLayout.SOUTH); } public void itemStateChanged(ItemEvent e){ int b = bold.isSelected()?Font.BOLD:Font.PLAIN; int i = italic.isSelected()?Font.ITALIC:Font.PLAIN; t.setFont(new Font("Serif",b + i,20));

121 程序运行结果如下图所示。

122 9.3.5 单选按钮(JRadioButton) 在一组单选按钮中,可进行选择其中一个的操作,即进行“多选一”。JRadioButton类的类层次和构造方法的参数构成都与前面介绍的JCheckBox类相同。这里不再列出JRadioButton类的这些内容。 因为单选按钮是在一组按钮中选择一个,因此,必须将单选按钮分组,即指明在一个组中包含哪些按钮。可用ButtonGroup创建按钮组对象,应用对象的add()方法顺序加入各个单选按钮。 在单选按钮中也可以使用HTML代码。这是Java SDK 1.3版新增的功能。 单选按钮的选择事件是ActionEvent类事件。

123 【例9.14】使用单选按钮来设置Swing应用程序的不同观感。
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class JRadioButtonDemo extends JPanel { static JFrame frame; static String metal= "Metal"; static String motif = "Motif"; static String windows = "Windows"; JRadioButton metalButton, motifButton,windowsButton; public JRadioButtonDemo(){ JButton button = new JButton("Hello, world"); button.setMnemonic('h'); metalButton = new JRadioButton(metal); metalButton.setMnemonic('o'); metalButton.setActionCommand(metal);

124 motifButton = new JRadioButton(motif);
motifButton.setMnemonic('m'); motifButton.setActionCommand(motif); windowsButton = new JRadioButton(windows); windowsButton.setMnemonic('w'); windowsButton.setActionCommand(windows); // 将单选按钮设置为一组 ButtonGroup group = new ButtonGroup(); group.add(metalButton); group.add(motifButton); group.add(windowsButton); // 对单选按钮设置监听器 RadioListener myListener = new RadioListener(); metalButton.addActionListener(myListener); motifButton.addActionListener(myListener);

125 windowsButton.addActionListener(myListener);
add(button); add(metalButton); add(motifButton); add(windowsButton); } /** ActionListener监听器监听单选按钮*/ class RadioListener implements ActionListener { // 嵌套类 public void actionPerformed(ActionEvent e) { if((e.getActionCommand()).equals(metal)) SetLAF.setJavaLookAndFeel(); else if((e.getActionCommand()).equals(motif)) SetLAF.setMotifLookAndFeel(); else SetLAF.setNativeLookAndFeel(); SwingUtilities.updateComponentTreeUI(frame);

126 程序运行时可用单选按钮选择三种不同的观感,运行结果如下图上、中和下所示。
frame.pack(); } public static void main(String s[]) { JRadioButtonDemo panel = new JRadioButtonDemo(); frame = new JFrame("使用JRadioButton选择观感"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); frame.getContentPane().add("Center", panel); frame.setVisible(true); 程序运行时可用单选按钮选择三种不同的观感,运行结果如下图上、中和下所示。

127 例9.14程序运行时选择不同单选按钮的界面。

128 9.3.6 文本框(JTextField、JPassWord和JTextArea)
Java语言提供了单行文本框、口令框和多行文本框等文本框形式,它们都是人机交互的主要组件。 1.单行文本框(JTextField) 单行文本框一般用来让用户输入如姓名、地址这样的信息,它是一个能够接收用户的键盘输入的单行文本区域。类JTextField提供对单行文本框的支持,它的类层次如下: javax.swing.Jcomponent └ javax.swing.text.JTextComponent └ javax.swing.JTextField JTextField类有如下的几种构造方法: JTextField( ) 创建一个新的单行文本框。

129 JTextField(int columns) 创建具有指定长度的空单行文本框。
JTextField(String text) 创建带初始文本内容的单行文本框。 JTextField(String text, int columns) 创建带初始文本内容并具有指定长度的单行文本框。 JTextField类的常用方法有: public void setText(String s)在文本框中显示字符串s。 public String getText()获得文本框中的字符串。 当用户在文本框里敲“回车”键时,就产生了一个ActionEvent事件。当用户在文本框中移动文本光标时,就产生CaretEvent事件,可注册addCaretListener监听器,实现CaretListener的caretUpdate()进行事件处理。

130 【例9.15】编写温度变换的应用程序,将摄氏温度转换为华氏温度。
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class CelsiusConverter implements ActionListener { JFrame frame; JPanel panel; JTextField tempCelsius; JLabel celsiusLabel, fahrenheitLabel; JButton convertTemp; public CelsiusConverter() { // 构造方法 frame = new JFrame("温度变换"); panel = new JPanel(); panel.setLayout(new GridLayout(2, 2));

131 tempCelsius = new JTextField();
celsiusLabel = new JLabel("摄氏温度 = "); convertTemp = new JButton("变换"); fahrenheitLabel = new JLabel("?华氏温度"); convertTemp.addActionListener(this); panel.add(tempCelsius); panel.add(celsiusLabel); panel.add(convertTemp); panel.add(fahrenheitLabel); frame.getContentPane().add( panel,BorderLayout.CENTER); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); frame.pack();// 显示变换程序 frame.setVisible(true); }

132 程序运行显示如下图所示。 public void actionPerformed(ActionEvent event) {
// 实现监听器接口 public void actionPerformed(ActionEvent event) { int tempF; tempF = (int)((Double.parseDouble( tempCelsius.getText())) * ); fahrenheitLabel.setText(tempF + " 华氏温度"); } public static void main(String[] args) { CelsiusConverter converter = new CelsiusConverter(); 程序运行显示如下图所示。

133

134 2.口令框(JPasswordField)
单行口令文本框JPasswordField类是JTextField类的子类。在JPasswordField对象中输入的文字会被其他字符替代,这个组件常用来在Java程序中输入口令。 JPasswordField类的构造方法与JTextField类的构造方法类似,常用的其他方法有: char[] getPassword() 返回输入的口令。 char getEchoChar() 返回输入文本时回显在框中的字符。回显字符缺省为字符“*”。 void setEchoChar(char c) 设置回显字符。

135 【例9.16】使用口令框。 import java.awt.*; import java.awt.event.*;
import javax.swing.*; public class JPasswordFieldDemo extends JApplet implements ActionListener{ JLabel jl1,jl2; JPasswordField jp1,jp2; JButton jb1,jb2; public void init(){ Container c = getContentPane(); jl1 = new JLabel( "<html><h3>请输入您的密码:" ,JLabel.CENTER); jl2 = new JLabel( "<html><h3>请再次输入密码:" ,JLabel.CENTER);

136 jp1 = new JPasswordField(8);
jb1 = new JButton("<html><h3>提交"); jb2 = new JButton("<html><h3>取消"); c.setLayout(new GridLayout(3,2)); c.add(jl1); c.add(jp1); c.add(jl2); c.add(jp2); c.add(jb1); c.add(jb2); jb1.addActionListener(this); jb2.addActionListener(this); }

137 public void actionPerformed(ActionEvent e){
if(e.getSource()==jb1) if(jp1.getPassword().length>0) if(String.valueOf(jp1.getPassword()).equals (String.valueOf(jp2.getPassword()))) showStatus("密码输入成功!"); else{ showStatus("两次输入的密码不同,请重新输入!"); jp1.setText(""); jp2.setText(""); } else showStatus("密码不能为空!"); if(e.getSource()==jb2){

138 showStatus(""); } 程序运行显示如下图所示。

139 3.多行文本框(JTextArea) JTextField 是单行文本框,不能显示多行文本,如果想要显示大段的多行文本,可以使用类JTextArea支持的多行文本框。JTextArea 有六个构造方法,常用的有四个: JTextArea() 创建空多行文本框。 JTextArea(int rows, int columns) 创建指定行列数的多行文本框。 JTextArea(String text) 创建带初始文本内容的多行文本框。 JTextArea(String text, int rows, int columns) 创建带初始文本内容和指定大小的多行文本框。 其中,text 为 JTextArea 的初始化文本内容;rows 为 JTextArea 的高度,以行为单位;columns 为 JTextArea 的宽度,以字符为单位。例如,构造一个高5行,宽15个字符的多行文本框的语句为: textArea = new JTextArea(5, 15);

140 多行文本框默认是不会自动折行的 (但可以输入回车符换行),可以使用类 JTextArea 的 setLineWrap(boolean wrap)方法设置是否允许自动折行。wrap为true时允许自动折行。多行文本框会根据用户输入的内容自动扩展大小。 若不自动折行,那么多行文本框的宽度由最长的一行文字确定的;若数据行数超过了预设的行数,则多行文本框会扩展自身的高度去适应。换句话说,多行文本框不会自动产生滚动条。这时,可用滚动窗格 (JScrollPane) 来为多行文本框增加滚动条。 滚动窗格是一个能够自己产生滚动条的容器,通常只包容一个组件,并且根据这个组件的大小自动产生滚动条。

141 多行文本框里文本内容的获得和设置,同样可以使用 getText()和 setText() 两个方法来完成。还可以用setEditable(boolean) 确定是否可对多行文本框的内容进行编辑。
【例9.17】使用带滚动条的多行文本框。 import javax.swing.*; import java.awt.*; public class JTAreaAndJSPaneDemo extends JFrame { public JTAreaAndJSPaneDemo(){ super("使用带滚动条的多行文本框"); JTextArea textArea = new JTextArea(5, 15); textArea.setLineWrap(true); JScrollPane jsp = new JScrollPane(textArea); getContentPane().add(jsp, BorderLayout.CENTER); pack();

142 程序运行显示如下图所示。 setDefaultCloseOperation(EXIT_ON_CLOSE); }
public static void main(String[] args) { JTAreaAndJSPaneDemo tp = new JTAreaAndJSPaneDemo(); tp.setVisible(true); 程序运行显示如下图所示。

143 9.3.7 列表框(JList) JList类的构造方法如下:
JList(Object[] listData) 构造显示指定数组listData中元素的JList对象。 例如,创建一个显示数组data中字符串的JList: String[] data = {"one","two","three", "four"}; JList dataList = new JList(data);

144 【例9.18】使用JList。 import java.awt.*; import javax.swing.*;
import javax.swing.event.*; import javax.swing.border.*; public class JListDemo extends JFrame { public static void main(String[] args) { new JListDemo(); } private JList jl; private JTextField valueField; public JListDemo() { super("一个简单的JList"); WindowUtilities.setNativeLookAndFeel(); addWindowListener(new ExitListener()); Container content = getContentPane(); String[] entries = { “北京”,“上海”, "天津","重庆","武汉"};

145 jl = new JList(entries); // 创建JList对象
jl.setVisibleRowCount(4); // 设置JList显示行数 Font displayFont = new Font("Serif", Font.BOLD, 18); jl.setFont(displayFont); jl.addListSelectionListener(new ValueReporter()); JScrollPane listPane = new JScrollPane(jl); JPanel listPanel = new JPanel(); listPanel.setBackground(Color.white); Border listPanelBorder = BorderFactory. createTitledBorder("JList数据"); listPanel.setBorder(listPanelBorder);//设置面板边界 listPanel.add(listPane); content.add(listPanel, BorderLayout.CENTER); JLabel valueLabel = new JLabel("选择为:");

146 valueLabel.setFont(displayFont);
valueField = new JTextField("", 6); valueField.setFont(displayFont); JPanel valuePanel = new JPanel(); valuePanel.setBackground(Color.white); Border valuePanelBorder = BorderFactory. createTitledBorder("JList选择"); valuePanel.setBorder(valuePanelBorder); valuePanel.add(valueLabel); valuePanel.add(valueField); content.add(valuePanel, BorderLayout.SOUTH); pack(); setVisible(true); }

147 程序的运行结果如图所示。 private class ValueReporter
implements ListSelectionListener { public void valueChanged(ListSelectionEvent event){ if (!event.getValueIsAdjusting()) valueField.setText( jl.getSelectedValue().toString()); } 程序的运行结果如图所示。

148 类JComboBox提供组合框的支持,其相关类的层次如下:
在Java语言中,组合框有可编辑的和不可编辑的两种不同的形式。缺省是不可编辑的组合框。这里对不可编辑的组合框进行介绍。组合框用于在多项选择中选择一项的操作。在未选择组合框时,组合框显示为带按钮的一个选项的形式,当对组合框按键或单击时,组合框会打开可列出多项的一个列表,提供给用户选择。 类JComboBox提供组合框的支持,其相关类的层次如下: javax.swing.Jcomponent └ javax.swing.JComboBox 类JComboBox()的构造方法有四种,常用的有两种: JComboBox()用缺省的数据模式创建组合框。 JComboBox(Object[] items)用指定数组创建组合框。

149 创建组合框后,可用方法setSelectedIndex(int anIndex)选定指定下标anIndex处的项目; 可用方法getSelectedIndex()获得选定项目的数组下标;可用方法getSelectedItem()获取选定的项目。 组合框事件是ActionEvent事件。事件处理方法与其他处理同类事件的方法类似。 【例9.19】使用JComboBox。 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class JComboBoxDemo extends JPanel { JLabel picture,text; public JComboBoxDemo() { String[] pStrings = {"cup","cat","boy","girl"};

150 JComboBox pList = new JComboBox(pStrings);
pList.setSelectedIndex(0); pList.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JComboBox cb = (JComboBox)e.getSource(); String pName = (String)cb.getSelectedItem(); picture.setIcon(new ImageIcon("images/“ + pName + ".gif")); text.setText(pName); text.setHorizontalAlignment(JLabel.CENTER); } }); picture = new JLabel(new ImageIcon("images/" + pStrings[pList.getSelectedIndex()] +".gif"));

151 picture.setBorder(BorderFactory.
createEmptyBorder(10,0,0,0)); picture.setPreferredSize(new Dimension(180, 140)); text = new JLabel(pStrings[pList.getSelectedIndex()], JLabel.CENTER); setLayout(new BorderLayout()); add(pList,BorderLayout.NORTH); add(picture,BorderLayout.CENTER); add(text,BorderLayout.SOUTH); setBorder( BorderFactory.createEmptyBorder(20,20,20,20)); } public static void main(String args[]) { JFrame frame = new JFrame("使用JComboBox");

152 程序的运行结果如下图所示。 frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new JComboBoxDemo()); frame.pack(); frame.setVisible(true); } 程序的运行结果如下图所示。

153 9.3.9 滚动条(JSlider) 可用下列JSlider类的构造方法生成JSlider对象。
在某些程序中,需要调整线性的值,这时就需要滚动条。滚动条提供了易于操作的值的范围或区的范围。javax.swing.JSlider类提供了对滚动条的支持,它的父类是javax.swing.JComponent类。 可用下列JSlider类的构造方法生成JSlider对象。 JSlider() 创建范围为0至100,初值为50的水平滚动条。 JSlider(int orientation) 创建范围为0至100,初值为50的水平或垂直滚动条。表示方向的值可为常量JSlider.HORIZONTAL和JSlider.VERTICAL,分别表示水平和垂直方向。 JSlider(int min, int max) 创建范围为min至max,初值为min和max平均值的水平滚动条。

154 JSlider(int min, int max, int value) 创建范围为min至max,初值为value的水平滚动条。
JSlider(int orientation, int min, int max, int value) 创建范围为min至max,初值为value的水平或垂直滚动条。 对创建的JSlider对象可显示数据刻度和数据值,也可设置边界等。与其他接口组件一样,滚动条产生一个可以控制的事件ChangeEvent。 【例9.20】使用JSlider。 import java.awt.*; import javax.swing.*; import javax.swing.event.*; public class JSliderDemo extends Jframe implements ChangeListener{

155 JLabel l1; int v1,v2; JSlider sl1,sl2; public static void main(String[] args) { new JSliderDemo(); } public JSliderDemo() { super("使用JSlider"); Container c = getContentPane(); c.setBackground(Color.white); sl1 = new JSlider(JSlider.VERTICAL,100,200,100); // 创建垂直滚动条 sl1.setMajorTickSpacing(50); // 设置大刻度间隔 sl1.setMinorTickSpacing(10); // 设置小刻度间隔 sl1.setPaintTicks(true); // 显示刻度 sl1.setPaintLabels(true); // 显示标注

156 sl1.addChangeListener(this); // 注册监听器
c.add(sl1, BorderLayout.WEST); sl2 = new JSlider(); // 创建水平滚动条 sl2.setBorder( BorderFactory.createTitledBorder( "JSlider(具有带标题的边框、刻度和标注)")); // 设置组件带标题的边界 sl2.setMajorTickSpacing(20); sl2.setMinorTickSpacing(5); sl2.setPaintTicks(true); //true:产生滚动条上的刻度 sl2.setPaintLabels(true); //true:显示刻度上的数据 sl2.addChangeListener(this); c.add(sl2,BorderLayout.SOUTH);

157 l1=new JLabel("垂直滚动条的值为:"+ 100+"水平滚动条的值为:"+50);
c.add(l1,BorderLayout.CENTER); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置框架关闭按钮事件 pack(); setVisible(true); } public void stateChanged(ChangeEvent e){ if(e.getSource()==sl1) v1=((JSlider)e.getSource()).getValue(); else if(e.getSource()==sl2) v2=((JSlider)e.getSource()).getValue(); l1.setText("垂直滚动条的值为:"+v1+ ",水平滚动条的值为:"+v2);

158 程序运行结果如下图所示。

159 菜单(JMenu) 菜单将一个应用程序的命令按层次化管理并组织在一起,是一种常用的GUI组件。常见的菜单为下拉式菜单和弹出式菜单(快捷菜单)等。 下拉式菜单包含有一个菜单条(也称为菜单栏,MenuBar),在菜单条上安排有若干个菜单(Menu),每个菜单又包含若干菜单项(MenuItem),每个菜单项对应了一个命令或子菜单项。它们构成一个应用程序的菜单系统。用鼠标或键盘选择对应一个命令的菜单项与选择一个按钮类似。使用菜单系统可方便地向程序分布命令。 在构建一个自己的菜单系统时,可按照菜单系统的层次,一步一步地进行。

160 (1)用类JMenuBar创建菜单条 (2)用类JMenu创建菜单 (3)用类JMenuItem创建菜单项
JMenuBar aMenuBar = new JMenuBar(); (2)用类JMenu创建菜单 用类JMenu的构造方法来创建菜单,其构造方法有: public JMenu()构造一个无文本的菜单。 public JMenu(String s)用字符串s作为文本来构造一个菜单。 例如: JMenu aMenu = new JMenu("文件"); // 创建“文件”菜单 (3)用类JMenuItem创建菜单项 类JMenuItem的构造方法有:

161 public JMenuItem()创建一个菜单项,但不设置文本和图标。
public JMenuItem(Icon icon)创建一个带图标的菜单项。 public JMenuItem(String text)创建一个具有指定文本的菜单项。 public JMenuItem(String text, Icon icon)创建具有文本和图标的菜单项。 public JMenuItem(String text,int mnemonic)创建具有文本和快捷字母的菜单项。 例如:JMenuItem aMenuItem = new JMenuItem("新建");// 创建“新建”菜单项

162 (4)将菜单项加入到菜单中,将菜单加入到菜单条中
可用JMenuBar类和JMenu类的add()方法完成添加工作。例如: aMenuBar.add(aMenu ); aMenu.add(aMenuItem); 另外,可用addSeparator()方法向菜单添加分隔线。 (5)将菜单条加入容器中 可向实现了MenuContainer接口的容器(如框架)加入菜单系统。在框架JFrame类中有方法: public void setJMenuBar(JMenuBar menubar) 可为框架设置菜单条。例如: JFrame aFrame = new JFrame(); aFrame.setJMenuBar(aMenuBar);

163 (6)处理菜单项选择事件 为了检测对菜单项作出的选择,要监听菜单项ActionEvent事件,选择一个菜单项正如选择了一个JButton按钮一样。事件处理的相关代码可见下例。 【例9.21】使用下拉菜单系统。 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class JMenuDemo extends JFrame implements ActionListener{ JLabel j1 = new JLabel( "请选择菜单:",JLabel.CENTER); JMenuItem aaMenuItem,baMenuItem; JMenuDemo(){ super("使用JMenu"); JMenuBar aMenuBar = new JMenuBar(); Icon i1 = new ImageIcon("images/girl.gif");

164 Icon i2 = new ImageIcon("images/boy.gif");
JMenu aMenu = new JMenu("菜单A"); JMenu bMenu = new JMenu("菜单B"); JMenuItem aaMenuItem = new JMenuItem("菜单项AA",i1); JMenuItem abMenuItem = new JMenuItem("菜单项AB",i2); JMenuItem baMenuItem = new JMenuItem("菜单项BA"); aMenuBar.add(aMenu); aMenuBar.add(bMenu); aMenu.add(aaMenuItem); aMenu.addSeparator(); aMenu.add(abMenuItem); bMenu.add(baMenuItem); aaMenuItem.addActionListener(this); abMenuItem.addActionListener(this); baMenuItem.addActionListener(this);

165 getContentPane().add(j1,BorderLayout.CENTER); }
setJMenuBar(aMenuBar); getContentPane().add(j1,BorderLayout.CENTER); } public void actionPerformed(ActionEvent e){ JMenuItem source = (JMenuItem)(e.getSource()); j1.setText("选择了菜单:"+source.getText()); j1.setHorizontalAlignment(JLabel.CENTER); public static void main(String args[]){ JFrame frame = new JMenuDemo(); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); frame.setVisible(true); frame.pack();

166 程序运行时选择了菜单A后的情况如下图所示。

167 9.3.11对话框 对话框是一种大小不能变化、不能有菜单的容器窗口,对话框不能作为一个应用程序的主框架,而必须包含在其他的容器中。Java语言提供多种对话框类来支持多种形式的对话框。 JOptionPane类支持简单、标准的对话框;JDialog类支持定制用户自己的对话框;JFileChooser类支持文件打开、保存对话框;ProgressMonitor类支持操作进度条控制对话框等。 对话框依赖于框架。当框架撤销时,依赖该框架的对话框也撤销。当框架图标化时,依赖它的对话框也从屏幕上消失。当框架窗口恢复时,依赖框架的对话框又返回屏幕。 下面介绍较简单的JOptionPane和JFileChooser类支持的对话框。

168 javax.swing.JOptionPane类继承于javax.swing.JComponent类,有七种构造方法,常用的有五种:
JOptionPane提供的对话框是模式对话框。当模式对话框显示时,它不允许用户输入到程序的其他的窗口。使用JOptionPane,可以创建和自定义问题、信息、警告和错误等几种类型的对话框。JOptionPane提供标准对话框的布局支持、图标、指定对话框的标题和文本、自定义按钮文本、允许自定义组件的对话框显示、指定对话框在屏幕上的显示位置等特性。 javax.swing.JOptionPane类继承于javax.swing.JComponent类,有七种构造方法,常用的有五种: JOptionPane()创建具有测试信息的JOptionPane对象。 JOptionPane(Object message) 创建显示message和缺省选项的JOptionPane对象。

169 JOptionPane(Object message, int messageType) 创建以messageType类型显示message和使用缺省选项的JOptionPane对象。
JOptionPane(Object message, int messageType, int optionType)创建显示指定类型信息和指定选项类型的JOptionPane对象。 JOptionPane(Object message, int messageType, int optionType, Icon icon) 创建显示指定类型信息和指定选项类型、图标的JOptionPane对象。 要显示简单的模式对话框,可以使用showMessageDialog()或showOptionDialog()方法。 它们的格式为(showMessageDialog()方法有重载): public static void showMessageDialog(Component parentComponent,Object message,String title,int messageType,Icon icon)throws HeadlessException

170 public static int showOptionDialog(Component parentComponent,Object message,String title,int optionType,int messageType,Icon icon,Object[] options,Object initialValue) throws HeadlessException 前者显示一个带一个“Ok”或“确定”按钮的对话框。后者显示自定义的对话框—可以显示具有定制文本的各种按钮,并可包含一个标准的文本信息或组件集合。 例如: JOptionPane.showMessageDialog( frame,"请输入一个整数。\n" + "无效输入。"); showXxxDialog方法的所有参数和JOptionPane构造方法都是标准化的, 下面对这些参数进行说明。 parentComponent 对每个showXxxDialog方法的第一个参数总是父组件,必须是一个框架、一个框架中的组件、或null值。JOptionPane构造方法不包含这个参数。

171 message 这个必须的参数指明要显示的对话框。一般是一个字符串,显示在对话框的一个标签中。 title 标题。
optionType 指定出现在对话框底部的按钮集合,可以选择下面4个标准集合之一: DEFAULT_OPTION,YES_NO_OPTION,YES_NO_CANCEL_OPTION,OK_CANCEL_OPTION。 messageType 确定显示在对话框中的图标。从下列值中选择一个:PLAIN_MESSAGE (无 icon), ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE. icon 指明了在对话框中显示用户定义图标。 options进一步指明任选对话框底部的按钮。一般地,对按钮指定一个字符串数组。 initialValue 指明选择的初始值。

172 showMessageDialog()和showOptionDialog()方法返回用户选择的一个整数,整数值为YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION和CLOSED_OPTION之一。除了CLOSED_OPTION的每一个选项都对应用户单击的按钮。当CLOSED_OPTION返回时,说明用户关闭了对话框窗口。 即使用户改变了标准对话框上按钮显示的字符串,返回值仍然为预定义的整数值之一。例如,一个YES_NO_OPTION对话框总是返回下列值之一:YES_OPTION、NO_OPTION或CLOSED_OPTION。

173 【例9.22】使用对话框。 import javax.swing.*; import java.awt.*;
import java.awt.event.*; public class JOptionPaneDemo{ public JFrame aFrame; public JButton aButton; public JOptionPane anOptionPane; static JLabel aLabel; public JOptionPaneDemo(){ aFrame = new JFrame("使用JOptionPane"); aButton = new JButton("显示对话框"); aLabel = new JLabel(“您作出的选择是:”, JLabel.CENTER); aButton.addActionListener(new OptionListener()); anOptionPane = new JOptionPane();

174 aFrame.setSize(300,200); aFrame.getContentPane().add(aButton, BorderLayout.NORTH); aFrame.getContentPane().add(aLabel, BorderLayout.SOUTH); aFrame.setVisible(true); aFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); } public class OptionListener implements ActionListener{ public void actionPerformed(ActionEvent e){ String[] choices = {"喜欢", "不喜欢"}; int n = anOptionPane.showOptionDialog(aFrame, "您喜欢音乐吗?", "请选择",

175 程序运行时显示的 对话框如下图所示。 JOptionPane.QUESTION_MESSAGE, null,
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, choices,choices[0]); if(n == 0) JOptionPaneDemo.aLabel.setText("喜欢音乐"); else JOptionPaneDemo.aLabel.setText("不喜欢音乐"); } public static void main( String[] args){ new JOptionPaneDemo(); 程序运行时显示的 对话框如下图所示。

176 2.JFileChooser对话框 JFileChooser类提供对文件的打开、关闭等文件操作的标准对话框。
JFileChooser类继承于JComponent类,其构造方法有: JFileChooser()构造一个指向用户缺省目录的JFileChooser对象 。 JFileChooser(File currentDirectory)构造一个以给定File为路径的JFileChooser对象。 构造JFileChooser对象后,要利用该类的方法showOpenDialog()或showSaveDialog()来显示文件打开或文件关闭对话框。它们的格式为: public int showOpenDialog(Component parent)throws HeadlessException

177 public int showSaveDialog(Component parent)throws HeadlessException
它们的参数都是包含对话框容器的对象。返回值为下面几种情况: JFileChooser.CANCEL_OPTION 表示选择了“撤消”按钮。 JFileChooser.APPROVE_OPTION 表示选择了“打开”或“保存”按钮。 JFileChooser.ERROR_OPTION 表示出现错误。 在打开或关闭文件对话框中作出选择后,可用JFileChooser类的方法getSelectedFile()返回选取的文件名(File类的对象)。

178 【例9.23】使用文件打开、关闭对话框(JFileChooser)。将选择的文件名显示到文本区域中。
import java.io.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.filechooser.*; public class JFileChooserDemo extends JFrame { public JFileChooserDemo() { super("使用JFileChooser"); final JTextArea ta = new JTextArea(5,20); ta.setMargin(new Insets(5,5,5,5)); ta.setEditable(false); JScrollPane sp = new JScrollPane(ta); final JFileChooser fc = new JFileChooser(); JButton openBtn = new JButton("打开文件...");

179 openBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) { int returnVal = fc.showOpenDialog( JFileChooserDemo.this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); ta.append("打开: " + file.getName() + ".\n"); } else ta.append("取消打开命令.\n"); } }); JButton saveBtn = new JButton("保存文件..."); saveBtn.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ int returnVal = fc.showSaveDialog(

180 if (returnVal == JFileChooser.APPROVE_OPTION){
File file = fc.getSelectedFile(); ta.append("Saving: " + file.getName() + ".\n"); } else ta.append("取消保存命令。\n"); } }); JPanel buttonPanel = new JPanel(); buttonPanel.add(openBtn); buttonPanel.add(saveBtn); openBtn.setNextFocusableComponent(saveBtn); saveBtn.setNextFocusableComponent(openBtn); Container c = getContentPane(); c.add(buttonPanel, BorderLayout.NORTH); c.add(sp, BorderLayout.CENTER);

181 public static void main(String[] args) {
JFrame frame = new JFileChooserDemo(); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } 程序运行的开始界面如下图左,选择“打开文件”按钮后,即出现下图右的打开文件对话框,选择文件后将选择文件名显示到文本区域中。选择“保存文件”按钮,将出现文件保存对话框。

182 例9.23的运行界面。

183 9.4 鼠标和键盘事件 在GUI程序中,通常使用鼠标来进行人机交互操作。鼠标的移动、单击、双击等都会引发鼠标事件。为输入数据、操作命令等,也使用键盘。键盘的按下,释放也会引发键盘事件。下面简单介绍AWT的鼠标和键盘事件的处理。

184 接口MouseListener中的方法为:
9.4.1 鼠标事件 处理鼠标事件的程序要实现在java.awt.event包中定义的两个接口MouseListener和MouseMotionListener,在这两个接口中定义了未实现的鼠标事件处理方法。 接口MouseListener中的方法为: public void mousePressed(MouseEvent e)处理按下鼠标左键 public void mouseClicked(MouseEvent e)处理鼠标单击 public void mouseReleased(MouseEvent e)处理鼠标按键释放 public void mouseEntered(MouseEvent e)处理鼠标进入当前窗口 public void mouseExited(MouseEvent e)处理鼠标离开当前窗口

185 【例9.24】通过单击鼠标来画蓝色的圆点。 接口MouseMotionListener中的方法为:
public void mouseDragged(MouseEvent e)处理鼠标拖动 public void mouseMoved(MouseEvent e)处理鼠标移动 对应上述接口,对应的注册监听器的方法是addMouseListener()和addMouseMotionListener()。 另外,类MouseEvent的方法getX()、getY()常用来获取鼠标当前所在位置的坐标,它们的格式如下: public int getX() public int getY() 【例9.24】通过单击鼠标来画蓝色的圆点。

186 import javax.swing.*; import java.awt.event.*; import java.awt.*; public class MouseEventDemo extends JApplet{ public void init(){ addMouseListener(new CircleListener()); setForeground(Color.blue); setBackground(Color.white); } class CircleListener extends MouseAdapter { private int radius = 10; public void mousePressed(MouseEvent e) { JApplet app = (JApplet)e.getSource();

187 程序运行结果如下图所示。 g.fillOval(e.getX()-radius,e.getY()-radius,
Graphics g = app.getGraphics(); g.fillOval(e.getX()-radius,e.getY()-radius, 2*radius,2*radius); } 程序运行结果如下图所示。

188 9.4.2 键盘事件 处理键盘事件的程序要实现在java.awt.event包中定义的接口KeyListener,在这个接口中定义了未实现的键盘事件处理方法。键盘事件处理方法为: public void KeyPressed(KeyEvent e)处理按下键。 public void KeyReleased(KeyEvent e)处理松开键。 public void KeyTyped(KeyEvent e)处理敲击键盘。 为识别引发键盘事件的按键,常用到KeyEvent类的如下方法: public char getKeyChar()返回该事件中键的字符。例如,shift + "a"按键事件返回值为"A"。 public static String getKeyText(int keyCode)返回描述键代码的字符串,例如"HOME"、"F1" 或"A"等。

189 【例9.24】综合鼠标事件和键盘事件处理的程序,模拟一个电子白板,可以用鼠标在上面绘画,可用键盘在上面写字。
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class MouseAndKeyDemo extends JApplet { protected int lastX = 0, lastY = 0; public void init() { setBackground(Color.white); setForeground(Color.blue); addMouseListener(new PositionRecorder()); addMouseMotionListener(new LineDrawer()); addKeyListener(new CharDrawer()); } protected void record(int x, int y) {

190 private class PositionRecorder extends MouseAdapter{
lastX = x; lastY = y; } private class PositionRecorder extends MouseAdapter{ public void mouseEntered(MouseEvent e) { requestFocus(); record(e.getX(), e.getY()); public void mousePressed(MouseEvent e) { private class LineDrawer extends MouseMotionAdapter { public void mouseDragged(MouseEvent e) { int x = e.getX(),y = e.getY();

191 Graphics g = getGraphics();
g.drawLine(lastX, lastY, x, y); record(x, y); } private class CharDrawer extends KeyAdapter { public void keyTyped(KeyEvent event) { String s = String.valueOf(event.getKeyChar()); getGraphics().drawString(s, lastX, lastY); record(lastX + 11, lastY);

192 程序中,在类MouseAndKeyDemo中定义了三个私有嵌套类,两个类对鼠标事件进行处理,一个类对键盘事件进行处理。
程序的运行情况如下图所示。图中的线用鼠标随手画出,文字用键盘输入。

193 本章小结 本章主要介绍了Java中GUI应用程序设计的方法,要求大家掌握如下内容:
Java中awt包中基本组件的使用及绘图方法 Java中swing包中组件的使用 Java中常用鼠标及键盘事件的处理 要求大家通过本章内容的学习,能够创建简单的图形用户界面的应用程序。


Download ppt "第9章 图形用户界面(GUI)设计."

Similar presentations


Ads by Google