《Java语言程序设计》课件第6章_第1页
《Java语言程序设计》课件第6章_第2页
《Java语言程序设计》课件第6章_第3页
《Java语言程序设计》课件第6章_第4页
《Java语言程序设计》课件第6章_第5页
已阅读5页,还剩226页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

6.1GUI程序框架

6.2容器布局ContainerLayout

6.3事件处理

6.4基本Swing组件编程

6.5高级Swing组件编程

6.6小结

6.7习题

6.1.1GUI类层次图

如图6-1所示,GUI(GraphicsUserInterface)编程主要以java.awt.Component包为主,要建立GUI程序还必须包含容器类Container,而Container又包括Panel、Window和javax.swing.JComponent。Panel容器包括Applet和JApplet的子类,Window容器分为Frame和Dialog,由这两种类再派生出JFrame和JDialog。java.awt.Component包含各种Swing组件,诸如JButton、JTextArea、JTabel等。6.1GUI程序框架图6-1GUI类层次图6.1.2程序框架

GUI图形用户界面用于编写基于图形化的界面,便于用户与计算机进行交互,它比前面讲述的基于命令行窗口的Application更加友好。要进行GUI编程,就要掌握AWT(AbstractWindowToolkit,抽象窗口工具包),它是Java为了适应各种不同操作的图形化编程而抽象出的若干图形化的窗口组件的工具集合。AWT提供了各种容器、布局管理以及各种组件,其类层次如图6-1所示。AWT在编程实践中又有一定局限性,因此轻量级组件包javax.swing应运而生。与AWT组件相比,Swing组件具有更加优秀的特性(将在后续章节中讲述),因此我们主要以Swing组件为基础来讲述。要建立GUI程序,就需要将各种各样的组件组合在一起,按照一定的排列方式排列起来,这就需要一个能够容纳组件的对象——容器。容器可对各种组件的布局进行管理。

常见的容器如图6-1所示,有Panel、javax.swing.JComponent和Window。Window类的子类Dialog和Frame又派生出了JDialog和JFrame。JDialog是特殊的容器,其位置可以移动,但不能改变其大小,我们在后续章节讲述。本节主要介绍JFrame。

JFrame是一个大小可以调整、位置可以移动的窗体。Panel类派生出了JPanel、Applet及JApplet,Applet和JApplet是一种特殊的程序,主要运行在Web上,我们在后续章节中讲述,本节我们主要讲述JPanel。因此,本节我们主要讲述构成程序框架的两个关键容器JPanel和JFrame。

1. JPanel

JPanel不能独立存在,只能加在别的容器中使用,如JFrame、JDialog等。JPanel类由Panel派生而得到,Panel还有一个Applet子类和JApplet(Applet的子类),JApplet和Applet是运行在Web上的小应用程序,下一章节将详细介绍。一个JPanel区域是一个矩形的区域,因为它本身是一个容器类,因此在其中可以添加其他组件对象,诸如JButton、JLabel等。

JPanel()直接构造一个空的JPanel对象,应用add(object)方法可以将其他组件加入到JPanel容器中。JPanel通常不可视,只有当其添加到JFrame中后,才可显示。

如例6-1所示,先构造一个JFrame对象、一个JPanel对象和一个JLabel对象,将JLabel对象lb加入到容器JPanel的对象jp中,再将jp对象添加到JFrame的对象frm中。程序运行结果如图6-2所示。图6-2JPanel的使用【例6-1】JPanel示例程序。

importjavax.swing.*;

publicclassMyJPanelextendsJFrame

{

publicstaticvoidmain(String[]args)

{

Iconicn=newImageIcon("images/Student1.jpg");

JLabellb=newJLabel(icn);

JPaneljp=newJPanel();

JFramefrm=newJFrame("JPanel测试示例");

jp.add(lb);

frm.add(jp);

frm.setSize(200,160);

frm.setVisible(true);

frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

2. JFrame图6-3JFrame的使用

应用JFrame()可以构造一个空的窗口对象;应用JFrame(Stringtitle)可以构造一个窗口标题为title的窗口;应用add(object)方法可以将各种组件添加到窗口中,应用setSize(intwindth,intheigh)可以设置JFrame窗口的宽度和高度;应用frameobject.pack()方法,可以使窗口自动调整尺寸,以适应其中组件的大小;应用setVisable()可以使窗口显示(true)或隐藏(false);应用setDefaultCloseOperation()方法,其中参数为静态常量“JFrame.EXIT_ON_CLOSE”,可以设置窗体响应关闭命令。

JFrame的使用如例6-2所示,其运行结果如图6-3所示。

【例6-2】JFrame应用示例。

importjavax.swing.*;

publicclassMyJFrameextendsJFrame

{

publicstaticvoidmain(String[]args)

{

JFramef=newJFrame("JFrame测试示例");

JButtonbtn=newJButton("PleaseClickme!");

f.add(btn); f.setSize(200,100);

f.setVisible(true);

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

JFrame程序中若没有事件侦听处理Window退出事件,或没有setDefaltCloseOperation,则点击窗口的“×”时,无法完全退出系统,必须按“Ctrl + C”键才能中断退出当前运行程序。图6-3JFrame的使用在GUI编程时,所有的组件必须盛放在一个容器中,这些组件的排列方式、大小都由布局管理器来控制。每个容器Container(如Panel或Frame)都有一个与它相关的缺省布局管理器,它可以通过调用setLayout()来改变容器中组件的布局方式。

6.2容器布局ContainerLayout

Java中常用的几种布局格式如下:

FlowLayout:流布局格式,一般在Panel或Applet中是缺省的布局格式。

BorderLayout:边界布局格式,一般在Window、Frame中是缺省的布局格式。

此外还有GridLayout布局格式、CardLayout布局格式和GridBagLayout布局格式。6.2.1FlowLayout布局

采用FlowLayout布局时,所有的组件按照顺序排列,逐行定位,当一行上放置不下时转到新一行再进行放置组件。当用户对一个采用FlowLayout布局的区域进行缩放时,布局也会发生变化,如原本为一行三个组件,当Window缩小时可能只能放置两个组件,第三个组件便会顺序推至下一行。与其它布局管理器不同的是,FlowLayout布局管理器不限制它所管理的组件的大小,而是允许它们有自己的最佳大小。可以通过参数来设置组件之间的间隔,也可以通过参数来设定组件的对齐格式,如左右对齐、居中对齐等。

例6-3是通过setLayout(newFlowLayout(intalign,inthgap,intvgap));来设置布局的,setLayout()中的内容为一个匿名的流布局管理器对象,intalign参数用来设置组件对齐格式,通常有FlowLayout.LEFT、FlowLayout.RIGHT、FlowLayout.CENTER、FlowLayout.LEADING或FlowLayout.TRAILING几个常量;inthgap整型参数为组件间的水平间距(像素值);intvgap为组件间的垂直间距。【例6-3】FlowLayout布局示例。

importjava.awt.*;

publicclassMyFlowLayout

{

publicstaticvoidmain(Stringargs[])

{

Framef=newFrame(“FlowLayout布局示例”);

f.setLayout(new

FlowLayout(FlowLayout.CENTER,5,5));

Buttonbutton1=newButton("Ok");

Buttonbutton2=newButton("Open");

Buttonbutton3=newButton("Close"); f.add(button1);

f.add(button2);

f.add(button3);

f.setSize(100,100);

f.setVisible(true);

}

}其中,Framef=newFrame("FlowLayout布局示例")语句创建一个Title是“FlowLayout布局示例”的框架;f.setLayout(newFlowLayout(FlowLayout.CENTER,5,5))语句用于设置该框架内部组件以Flow布局方式放置,居中对齐,水平和垂直间距都为5个像素值;newButton("Ok")语句用于创建一个显示“OK”的按钮并通过f.add(button1)将该按钮添加到Frame中;f.setVisible(true)使该框架变为可视内容。这些语句将在本章下一节详细讲解。FlowLayout布局结果见图6-4。图6-4FlowLayout布局及区域变化后的FlowLayout布局6.2.2BorderLayout布局

采用BorderLayout布局管理器时,其布局稍稍复杂一些,它把整个容器分为北、南、西、东、中(North、South、West、East、Center)五个区域,这五个区域按照地图的布局“上北下南左西右东”分布,中间是“Center”区域。

BorderLayout布局格式是Frame或Dialog容器的缺省布局格式。

采用BorderLayout布局时其位置保持相对不变,而区域中组件的大小随着区域的变化而变化,例6-4运行后的结果如图6-5所示。当区域缩小时,五个按钮的位置相对不变,而按钮大小发生变化。图6-5BorderLayout布局格式及其区域变化后布局【例6-4】BorderLayout布局示例。

importjava.awt.*;

publicclassMyBorderLayout

{

publicstaticvoidmain(Stringargs[])

{

Framef=newFrame("BorderLayout布局示例"); f.setLayout(newBorderLayout());

Buttonbn=newButton("B1");

Buttonbs=newButton("B2");

Buttonbe=newButton("B3");

Buttonbw=newButton("B4");

Buttonbc=newButton("B5");

f.add(bn,BorderLayout.NORTH); f.add(bs,BorderLayout.SOUTH);

f.add(be,BorderLayout.EAST);

f.add(bw,BorderLayout.WEST);

f.add(bc,BorderLayout.CENTER);

f.setSize(150,150);

f.setVisible(true);

}

}其中,f.setLayout(newBorderLayout())行代码设定区域布局为Border布局;f.add(bn,BorderLayout.NORTH)等五行程序将五个按钮添加进North等五个不同区域。一般情况下,五个区域中每个区域只能添加一个组件,若添加多个组件,则最后添加的一个组件可视。如果要实现每个区域添加多个组件,则可对每个区域再设置布局(如Flow布局)来实现。6.2.3GridLayout布局

采用GridLayout布局管理器时,它把容器分为若干行和列的单元格,每个单元格中可以添加组件。若例6-5中,把区域分成2行3列或者3行2列,然后将6个按钮添加到每个单元格中,添加时顺序遵从先行后列,即从第一行第一列开始,然后第一行第二列,依次当第一行满时转至第二行,如图6-6(b)所示。采用GridLayout布局时,组件的大小与布局的行列数有关,GridLayout布局管理器依据行数来平均分配整个容器的垂直高度,依据列来平均分配水平宽度。

当在GridLayout布局管理器中添加超过行数和列数的组件时,最后添加的组件是可视的,一般对列进行扩展,而行数保持不变,如图6-6(c)所示,行列数设置为3行2列,而实际添加组件数为9个,则列进行扩展。图6-6GridLayout布局格式及行列变化后的布局(a)

(b)

(c)【例6-5】GridLayout布局示例。

importjava.awt.*;

publicclassMyGridLayout

{

publicstaticvoidmain(Stringargs[])

{

Framef=newFrame("GridLayout布局示例"); f.setLayout(newGridLayout(3,2));

Buttonb1=newButton("1");

Buttonb2=newButton("2");

Buttonb3=newButton("3");

Buttonb4=newButton("4");

Buttonb5=newButton("5");

Buttonb6=newButton("6");

f.add(b1);f.add(b2);f.add(b3);

f.add(b4);f.add(b5);f.add(b6);

f.pack();

f.setSize(150,150);

f.setVisible(true);

}

}6.2.4CardLayout布局

CardLayout布局格式就像卡片一样,可以叠放多个页面,但界面中每次只能显示一个页面。例6-6中,叠放了五个Panel,每个Panel的背景颜色不同,且上面显示的文字也不同,当调用f.add添加时,每个Panel有一个别名;当调用myCard.show(f,“First”)时,则显示具体的每个Panel。

【例6-6】CardLayout布局示例。importjava.awt.*;

importjava.awt.event.*;

publicclassMyCardLayout

{

publicstaticvoidmain(Stringargs[])

{

Framef=newFrame("CardLayout布局示例");

CardLayoutmyCard=newCardLayout();

f.setLayout(myCard);f.add(p1,“First”);f.add(p2,“Second”);f.add(p3,“Third”);

f.add(p4,“Fourth”);f.add(p5,“Fifth”);

myCard.show(f,“First”);

//myCard.show(f,“Fourth”);

f.setSize(150,150);

f.setVisible(true);

}

}

图6-7为CardLayout布局及显示不同的Panel。图6-7CardLayout布局及显示不同的Panel(a)

(b)6.2.5GridBagLayout布局

与前几种布局管理器不同,GridBagLayout的网格包布局管理器提供了更加复杂的布局管理格式,前几种组件的大小都可以随区域变化而改变,GridBagLayout布局使得组件大小更趋优化。GridBagLayout布局无需让组件占满一个布局区域,而是使用更加合理的尺寸,同时在GridBagLayout布局时,一个组件还可以同时占据若干个布局区域,这是前几种布局管理器所不具有的特点。例6-7中,使用GridBagLayout布局首先创建GridBagLayout的布局管理器对象,然后将容器设置为GridBagLayout布局,GridBagLayoutgb=newGridBagLayout();

Container.setLayout(gb);随后创建GridBagConstraints对象。然后设置第一个组件的GridBagConstraints属性,并告知布局管理器第一个组件的GridBagConstraints属性(即layout.setConstraints(Component1,Constraints);语句),再在容器中添加第一个组件。同理加入第二个、第三个组件,依次类推。其中Constraints有四个属性:constraints.gridx、constraints.gridy、constraints.gridwidth、constraints.gridheight,分别是组件的顶点横、纵坐标以及组件占用网格的行数和列数。如图6-8所示,按钮“一”的gridheight=2,则占据2行;按钮“四”的gridwigth=2,则占据2列。(a)(b)图6-8GridbagLayout布局及fill属性设置效果此外,fill属性可设置水平、垂直位置的空区域填充,如图6-8(b)所示;weightx和weighty属性分别设置水平和垂直填充空白区域的权值。其他属性请查阅JDK1.6API文档。

【例6-7】GridBagLayout布局示例。

importjava.awt.*;

importjava.awt.event.*;

importjavax.swing.*;

publicclassMyGridBagLayoutextendsJPanel

{GridBagConstraintsconstraints=newGridBagConstraints();

publicMyGridBagLayout()

{

setLayout(newGridBagLayout());

//constraints.weightx=1.0;

//constraints.weighty=1.0;

constraints.fill=GridBagConstraints.BOTH;

intx,y;constraints.gridheight=2;

addGB(newJButton("一"),x=0,y=0);

constraints.gridheight=1;

addGB(newJButton("二"),x=1,y=0);

addGB(newJButton("三"),x=2,y=0);

constraints.gridwidth=2;

addGB(newJButton("四"),x=1,y=1);

constraints.gridwidth=1;

}voidaddGB(Componentcomponent,intx,inty){

constraints.gridx=x;

constraints.gridy=y;

add(component,constraints);

}

publicstaticvoidmain(String[]args){

JFramef=newJFrame("GridBag布局示例");

f.addWindowListener(newWindowAdapter(){

publicvoidwindowClosing(WindowEvente){System.exit(0);}});

f.setSize(200,150);

f.setContentPane(newMyGridBagLayout());

f.setVisible(true);

}

}

例6-7中,f.addWindowListener(newWindowAdapter()…});语句是为当前JFrame添加一个事件侦听器,作为鼠标关闭窗体使用。事件侦听内容将在6.3节详细讲述。6.2.6复杂布局

前面讲述的五种布局格式功能比较单一,单独使用时会有种种限制,但如果将这五种布局格式综合起来使用,即在一种布局格式中嵌套其他的布局格式,这样会使得布局更趋合理。

例6-8中,在屏幕左边是工具栏区域,中间是工作区域,上面是菜单区域。要实现这样的布局,就要在BorderLayout布局的North区域放置两个按钮,即采用布局的嵌套方式。【例6-8】复杂布局格式示例。

importjava.awt.*;

publicclassMutLayout

{

publicstaticvoidmain(Stringargs[])

{

Framef=newFrame("复杂布局格式示例");

Buttonbw=newButton("工具栏");

Buttonbc=newButton("工作区域");

f.add(bw,BorderLayout.WEST); f.add(bc,BorderLayout.CENTER);

Panelp=newPanel();

Buttonbfile=newButton("文件(F)");

Buttonbhelp=newButton("帮助(H)");

p.add(bfile);

p.add(bhelp);

f.add(p,BorderLayout.NORTH);

f.setSize(200,150);

f.setVisible(true);

}

}如图6-9所示,整个Frame的布局为BorderLayout布局,West中加入“工具栏”,Center中加入“工作区域”,North中加入菜单,即两个按钮分别是“文件”和“帮助”;同时在North中放置一个Panel,再将Panel设置为FlowLayout布局,然后将两个按钮按顺序加入Panel。图6-9复杂布局格式6.3.1委托事件模型

所谓事件源就是一个事件的产生者。如在Button组件上点击鼠标会产生以这个Button为源的一个ActionEvent,这个ActionEvent实例是一个对象,它是包含关于刚才所发生的那个事件的信息的对象。

事件处理器就是一个接收事件、解释事件并处理用户交互的方法。6.3事件处理在JDK1.0中采用的是层次模型,层次模型是基于容器的。事件先发送到组件,然后沿容器层次向上传播。没有被组件处理的事件会自动地继续传播到组件的容器。例如在Frame中嵌入一个Panel,在Panel中添加一Button对象,当鼠标点击此按钮时就会发送一个事件,如果事件没有被Button处理,这个事件会被送往Panel,如果仍然没有被处理,这个事件会被送往Frame,这样逐层上行就形成一种层次处理的事件模型。层次处理模型存在于早期版本中,从JDK1.1至后续版本采用的都是委托事件模型,这里我们不深入讨论层次模型而是主要讲述委托事件模型。委托事件模型下,每个可以触发事件的组件被当作事件源,每一种事件都有单独的事件侦听器,该事件侦听器只负责接收和处理这一种事件。一个事件源可以触发多个事件,只有当该事件源注册了几种事件侦听器时,这几种事件才会被接收和处理。因为事件源自身不处理事件,触发的事件交由事件侦听器来处理,所以这种事件处理模式被称为委托事件模型。

图6-10就是一个典型的委托事件模型。事件源是Frame,对Frame注册了KeyListener的键盘事件侦听器,则当Frame触发键盘事件时,就由KeyListener来处理键盘事件。虽然Frame也能触发鼠标事件,但由于事件源Frame并没有注册鼠标事件侦听器,因此Frame的鼠标事件就不发送。

委托事件模型如例6-9所示,运行结果如图6-11所示。图6-10委托事件模型实例图6-11委托事件模型【例6-9】委托事件模型示例。

importjava.awt.*;

publicclassEventModel

{

publicstaticvoidmain(Stringargs[])

{

Framef=newFrame("委托事件模型示例"); Buttonb=newButton("请点击按钮!");

b.addActionListener(newButtonHandler());

f.add(b,"Center");

f.setSize(200,100);

f.setVisible(true);

}

}例6-9中,b.addActionListener()为按钮b添加了一个行为事件侦听器,这个事件侦听器类作如下定义:

importjava.awt.event.*;

publicclassButtonHandlerimplementsActionListener

{

publicvoidactionPerformed(ActionEvente)

{ System.out.println("产生事件");

System.out.println("按钮的标签是:"+e.getActionCommand());

}

}

当我们点击图6-11中的左窗口按钮时,其响应按钮的鼠标点击事件,在事件中输出结果,见图6-11右窗口。6.3.2事件侦听接口

Java中大部分事件类集中在java.awt.event的包中,也有一些特殊事件存在于其它包中。每类事件都由一个接口来实现,这个接口不仅需由相应接收这个事件的对象来实现,同时还需要定义一个或多个方法来做各种处理。当事件发生时,就会调用这些方法。表6-1是Java中常见的事件源、实现的接口即事件侦听接口、触发事件后执行的方法。表6-1事件源、侦听接口和方法表6-1中,例如Action事件,其事件侦听接口为ActionListener,使用addActionListener方法就可以为某个组件添加Action类事件的侦听接口;当事件侦听接口侦听到事件发生时,就会执行ActionPerformed()方法;在ActionPerformed中添加代码即可实现对Action类事件的处理。其余类型事件相似,这里不再详述。

委托事件模型允许同一个组件可以有多个侦听接口。编程通过多次调用addXXXlistener方法来实现。6.3.3事件适配器

Java语言中,为了减小编程的工作量,提供了一个Adapter类,用于实现Listener侦听接口,编程时只需重写Adapter适配器类所提供的方法即可。例如,MouseListener接口定义了如下方法:mouseClicked()、mouseEntered()、mouseExited()、mousePressed()和mouseReleased()等方法,要实现MouseListener侦听接口,编程时可以继承鼠标事件的适配器MouseAdapter类,然后重写该类所需要的方法就可以了。上述实现过程如例6-10所示。【例6-10】事件适配器示例。

importjava.awt.*;

importjava.awt.event.*;

publicclassAdapterTest

{

publicstaticvoidmain(Stringargs[])

{ Framef=newFrame("适配器测试示例"");

Buttonb=newButton("1");

b.addMouseListener(newMyMouseListener());

f.add(b,"Center");

f.setSize(150,100);

f.setVisible(true);

}

}classMyMouseListenerextendsMouseAdapter

{

intcount;

publicvoidmouseClicked(MouseEvente)

{

Buttonbtn=(Button)e.getSource();

btn.setLabel(newInteger(Integer.parseInt(btn.getLabel())+1).toString());

}

}在实现MyMouseListener接口时,继承了MouseAdapter的类并覆盖了其MouseClicked方法。在主程序中给按钮添加此MyMouseListener的侦听器,当点击按钮时,其Label数组随点击次数的增加而增加。运行结果如图6-12所示。

常用的事件适配器如表6-2所示。图6-12事件适配器实现事件侦听表6-2常用的事件适配器6.3.4匿名内部类实现事件侦听

在例6-10中,覆盖方法时,我们不能直接访问外部类的成员变量和方法,所以需添加一行语句Buttonbtn=(Button)e.getSource()来取得事件源,然后再对事件源进行操作。这种方法显得比较繁琐,而Java事件侦听大多采用匿名的内部类来直接访问外部类的成员属性和方法。例6-11中,b.addActionLiserer添加了一个匿名对象newActionListener(),在编写这个匿名内部类的方法actionPerformed()时,无需再获取事件源(例中语句标识),而是直接对按钮对象b实施操作。【例6-11】匿名内部类实现事件侦听示例。

importjava.awt.*;

importjava.awt.event.*;

publicclassAnonymousclassextendsFrame

{

Buttonb=newButton("1");

publicAnonymousclass(Stringtitle)

{ super(title);

b.addActionListener

(

newActionListener()

{

publicvoidactionPerformed(ActionEvente)

{

//Buttonb=(Button)e.getSource();

b.setLabel(newInteger(Integer.parseInt(b.getLabel())+1).toString()); }

}

);

add(b);

setSize(150,80);

setVisible(true); }

publicstaticvoidmain(String[]args)

{

newAnonymousclass("匿名内部类接口实现示例");

}

}

运行结果如图6-13所示。图6-13匿名内部类实现事件侦听为了能够实现GUI编程,JDK提供了AWT,用于在各种不同的操作系统平台下实现图形用户程序的编写。AWT提供了诸如Frame、Button、Label等各种组件,可以进行一些图形窗口界面的程序设计。

6.4基本Swing组件编程随着技术的发展,原有的AWT组件已经不能满足需要,于是在AWT组件的基础上产生了Swing组件。由图6-1可知,Swing组件是基于AWT组件的,AWT组件是Swing组件的父类。例如JFrame类,我们查看其源文件,首先导入java.awt.*的包,同时其类定义(如publicclassJframeextendsFrameimplementsWindowConstants{})继承了Frame类,因此这两种组件包的功能基本相似。

AWT是为了支持小应用程序Applet而设计的,早期的版本不支持打印、剪贴板等,其功能受到一定限制;此外,AWT是基于对等组件的体系结构,这都使得AWT具有局限性。因此,Swing组件应运而生。

Swing组件是纯Java语言编写的GUI组件,它与本地系统无关,可以跨平台使用。独立于本地平台的Swing组件称为轻量级组件,而依赖于本地操作系统平台的AWT组件称为重量级组件。

Swing组件与重量级组件相比,没有本地的对等组件,不像重量级组件那样要在本地不透明窗体中绘制,而轻量级组件在重量级组件的窗口上绘制。

下面主要以编程中最常使用的Swing组件为例来介绍GUI的图形编程。6.4.1按钮与标签

1. JButton组件

JButton组件提供了这样一种机制,即当点击按钮后执行一定的操作。

常用JButton的构造方法包括:

JButton():构造一个没有任何标记的空按钮。

JButton(Iconicon):构造一个显示有Icon对象指定图标的按钮。

JButton(Stringtext):构造一个显示有text指定文字的按钮。

JButton(Stringtext,Iconicon):构造一个既显示文字text又显示图标icon的按钮。

getIcon()和setIcon(IcondefaultIcon):获取按钮上的图标和设置按钮上所要显示的图标。

getText()和setText(Stringtext):获取按钮上显示的文字和设置按钮上所要显示的文字。

setEnabled(booleanb):设置按钮可用(true)或按钮不可用(false)。

此外还有setHorizontalAlignment(intalignment)、setVerticalAlignment(intalignment)、setHorizontalTextPosition(inttextPosition)、setVerticalTextPosition(inttextPosition)等构造方法,分别用于设置水平和垂直对齐方式以及按钮显示文字的水平和垂直位置。

操作按钮可以产生多种事件,不过程序通常只需响应点击按钮时产生的动作事件(ActiveEvent)。可使用addActionListener(ActionListenerl)方法给按钮添加事件侦听器。

2. JLabel标签

一个标签对象显示一行静态文本。程序可以改变文本,但用户不能改变。在编程时JLabel一般用作提示信息,它不会产生任何事件,所以使用相对简单。

常用JLabel的构造方法包括:

JLabel():构造一个空的JLabel。

JLabel(Iconimage):构造一个带图标的JLabel。

JLabel(Stringtext):构造一个显示文字内容为text的标签。

JLabel(Stringtext,Iconicon,inthorizontalAlignment):构造一个既显示文字又显示图标的标签。【例6-12】按钮和标签的使用。

importjava.awt.*;

importjavax.swing.*;

importjava.awt.event.*;

publicclassButtonLabelextendsJFrame{

Icon[]icons={

newImageIcon(“images/Student1.jpg”),

newImageIcon(“images/Student2.jpg”),

newImageIcon("images/Student3.jpg")

}; String[]name={“学生甲”,“学生乙”,“学生丙”};

JLabeljl;

JButton

b1=newJButton

(“下一学生”,newImageIcon(“images/right.gif”)),

b2=newJButton("上一学生",newImageIcon("images/left.gif"));

intn=0,i=icons.length;

publicButtonLabel()

{setLayout(newBorderLayout());

jl=newJLabel(name[n],icons[n],SwingConstants.CENTER);

add(jl,BorderLayout.CENTER);

JPaneljp=newJPanel();

jp.setLayout(newFlowLayout());

b2.setEnabled(false);

b1.addActionListener(newActionListener(){

publicvoidactionPerformed(ActionEvente){ n++;

jl.setIcon(icons[n]);

jl.setText(name[n]);

if(n==1)

b2.setEnabled(true);

if(n==i-1)

b1.setEnabled(false);

}

});

b2.addActionListener(newActionListener(){

publicvoidactionPerformed(ActionEvente){ n--;

jl.setIcon(icons[n]);

jl.setText(name[n]);

if(n==i-2)

b1.setEnabled(true);

if(n==0)

b2.setEnabled(false);

}

});

jp.add(b1);jp.add(b2); add(jp,BorderLayout.SOUTH);

}

publicstaticvoidmain(String[]args){

ButtonLabelf=newButtonLabel();

f.setTitle(“测试JButton和JLabel”);

f.setSize(300,250);

f.pack();

f.setVisible(true);

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

运行结果如图6-14所示。图6-14JButton和JLabel示例例6-12中创建了两个按钮b1、b2,它们既有文字显示又有图标(对应图形文件为left.gif和right.gif)。采用匿名内部类的方法给两个按钮添加事件驱动,当点击按钮时,JLabel上的文字和图标内容也随之改变。

学生照片的显示可通过JLabel的图标显示功能来实现,JPanel上既有图标又有文字的显示。6.4.2文本域与文本区域

文本域与文本区域都是允许用户输入字符的区域,文本域只允许用户输入一行字符,而文本区域允许用户输入多行字符。文本域类还可以派生出JPasswordField的子类,用于输入用户口令字所输入的口令字以特定的字符显示而使口令不可视。

1.文本域

文本域常使用JTextField(文本字段)构造方法:JTextField()可以构造一个列数为0、初始字符串为空的文本输入域;JTextField(Stringtext)可以构造一个列数为0、初始字符串为text的文本输入域;JTextField(intcolumns)可以构造一个初始字符串为空、列数为columns的文本输入域;JTextField(Stringtext,intcolumns)可以构造一个初始字符串为text、列数为columns的文本输入域。

在文本域中按回车键会引发ActionEvent事件。我们可以使用addActionListener

(ActionListenerl)给文本输入域设置一个事件侦听器。

此外,getColumns()方法可以获取文本输入域的列数,setColumns(intcolumns)可以设置文本输入域的列数。应用setFont(Fontf)还可以设置文本输入域中文字的字体。

2.文本区域

文本区域常使用JTextArea构造方法:JTextArea()可以构造一个行、列数为0,初始字符串为空的文本输入区域;JTextArea(Stringtext)可以构造一个指定初始字符串为text的文本输入区域;JTextArea(introws,intcolumns)可以构造一个指定行、列数分别为rows和columns的文本输入区域;JTextArea(Stringtext,introws,intcolumns)可以构造一个指定行、列数和初始字符串的文本输入区域。

应用setEditable(boolean)方法还可以将文本输入区域的内容设置为只读(false),用于显示一段说明性文字。与文本域不同,文本区域不会引发ActionEvent事件。

【例6-13】文本域与文本区域。

importjava.awt.*;

importjavax.swing.*;

importjava.awt.event.*;

publicclassMyTextextendsJFrame{

publicMyText()

{ setLayout(newBorderLayout());

JLabellabel1=newJLabel("学生姓名:");

finalJTextFieldtextField=newJTextField(30);

JLabellabel2=newJLabel("学生简介:");

finalJTextAreatxtArea=newJTextArea(6,30);

JButtonbtn1=newJButton("确定");

textField.addActionListener(newActionListener(){

publicvoidactionPerformed(ActionEvente){ txtArea.requestFocusInWindow();

}

});

btn1.addActionListener(newActionListener(){

publicvoidactionPerformed(ActionEvente){

textField.setText(null);

txtArea.setText(null);

}

});

JPaneljpTextField=newJPanel();

jpTextField.setLayout(newFlowLayout()); add(jpTextField,BorderLayout.NORTH);

JPaneljpTextArea=newJPanel();

jpTextArea.setLayout(newFlowLayout());

jpTextArea.add(label2);jpTextArea.add(newJScrollPane(txtArea));

add(jpTextArea,BorderLayout.CENTER);

add(btn1,BorderLayout.SOUTH);

} publicstaticvoidmain(String[]args){

MyTextf=newMyText();

f.setTitle("测试JTextField和JTextArea");

f.pack();

f.setVisible(true);

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

运行结果如图6-15所示。图6-15文本域与文本区域例6-13中添加了一个输入学生姓名的textField文本域,以及一个输入学生基本情况简介的文本区域。文本域添加了一个ActionListener的匿名内部类实现事件侦听,键入回车键后,将光标移到文本区域即可输入学生的基本简介。同时,在SOUTH区添加一个按钮,当按钮响应事件后,即清空文本域和文本区域中的内容。6.4.3复选框与单选按钮

1.复选框

复选框可通过JCheckBox来实现。JCheckBox是一个很小的方框,框旁边可以标有文字或图标。它有两种状态,即被选或未被选。即当用户点击某个复选框时,该复选框会从一种状态转变为另一种状态。

常见的JCheckBox构造方法包括:JCheckBox()可以构造一个空的复选框;JCheckBox(Iconicon)可以构造一个带图标的复选框;

JCheckBox(Iconicon,boolean selected)可以构造一个带图标、初始状态为被选择(true)的复选框;JCheckBox(Stringtext,Booleanselected)可以构造一个显示文字为text且初始被选择的复选框(true);JCheckBox(Stringtext,Iconicon,booleanselected)可以构造一个既显示文字又显示图标的且可以设置初始状态的复选框。此外,应用isSelected()方法可以获取当前复选框的选择状态,应用setSelected(booleanb)可以设置复选框的状态为被选择(true)或者不被选择(false)。

由于点击复选框可以引发ActiveEvent和ItemEvent事件,因此可以给复选框添加ActiveListener和ItemListener的侦听器来侦听复选框发生的事件。

2.单选按钮

单选按钮可通过JRadioButton来实现。JRadioButton是一个很小的圆,圆旁边可以标有文字或图标。与复选框相同,每个单选按钮有两种状态:被选或未被选。用户点击某个单选按钮时,该单选按钮会从一种状态转变为另一种状态。与复选框不同的是,在某一时刻同一组中的单选按钮只有一个被选择,选择某个单选按钮时,同一组中的其他单选按钮都会变为未被选;而同一组中的复选框同时可以有0个、1个或多个被选。常见的JRadioButton构造方法包括:JRadioButton()可以构造一个空的单选按钮;JRadioButton(Iconicon)可以构造一个带图标显示的单选按钮;JRadioButton(Iconicon,booleanselected)可以构造一个带图标且设置初始状态的单选按钮;JRadioButton(Stringtext,Booleanselected)可以构造一个显示文字为text且可以设置初始态是否被选择的单选按钮;JRadioButton(Stringtext,Iconicon,booleanselected)可以构造一个既有文字显示又有图标显示的且可以设置初始状态的单选按钮。单选按钮一般是两个或两个以上存在,没有单独存在的单选按钮,这些单选按钮存在于一个组中,且组中的单选按钮同时有且只能有一个被选择。添加组时我们首先创建一个javax.swing.ButtonGroup类的对象,然后调用add(AbstractButtonb)方法将单选按钮添加到ButtonGroup组中来。

点击单选按钮也会引发ActiveEvent和ItemEvent事件,可以给单选按钮添加ActiveListener和ItemListener的侦听器来侦听它们所引发的事件。【例6-14】单选按钮和复选框的使用。

importjava.awt.*;

importjavax.swing.*;

importjava.awt.event.*;

publicclassMyJCheckBoxRadioextendsJFrame{

privateJLabeljl1=newJLabel("姓名");

privateJTextFieldtf=newJTextField(10);

privateJLabeljl2=newJLabel("性别");

privateJRadioButtonrb1=newJRadioButton("男",true);

privateJRadioButtonrb2=newJRadioButton("女",false); privateButtonGroupbg=newButtonGroup();

privateJLabeljl3=newJLabel("参加社团");

privateJCheckBoxcb1=newJCheckBox("书画");

privateJCheckBoxcb2=newJCheckBox("文学");

privateJCheckBoxcb3=newJCheckBox("体育");

publicMyJCheckBoxRadio()

{ frame.pack();

frame.setVisible(true);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

运行结果如图6-16所示。图6-16单选按钮和复选框例6-14中,学生的性别选择使用单选按钮rb1和rb2,其JRadioButton添加在一个ButtonGroup组中,每次只能选择一个。学生参加社团的选择使用复选框,每个JCheckBox选项都可以选择。6.4.4组合框与列表框

1.组合框

JComboBox组合框与单选按钮有些类似,用户点击组合框右侧下三角,展开后会出现一些可选项目,这些可选项目中只能选择其中一个,而不能多选。

JComboBox(组合框)常见的构造方法包括:JComboBox()可以构造一个选项为空的组合框;JComboBox(Object[]items)可以构造一个选项为items数组项的组合框。其中ietms是Object类型的,因此它支持很多格式的选项数组,譬如文字、图像等。此外,应用addItem(ObjectanObject)可以向组合框中添加一个选项;应用removeItem

(ObjectanObject)可以删除一个选项;应用removeItem(IntanIndex)可以删除位置为anIndex的选项;应用removeAllItems()可以移除所有选项。

JComboBox可以触发ActionEvent和ItemEvent事件,通过给JComboBox添加ActionListener和ItemListener来实现事件侦听。

2.列表框

JList在屏幕上显示为若干行数的选项。列表框与复选框有些类似,可以实现多个选项的选择,JList和JComboBox的外观不同,JComboBox只有点击下拉小三角后才能显示若干个选项,而JList可直接列出所有选项。JList要实现多选时,按“Ctrl”键,点击不连续的选项实现不连续项的选择,或者按“Shift”键,点击首选项和末选项实现一段连续选项的选择。应用JList()可以构造一个空的JList的列表框;应用JList(Object[]listData)可以构造一个有listData对象数组指定选项的列表框。

应用getSelectedIndexes()可以获取JList中所选择项的索引值;应用getSelectedValues()可以获取JList中选中选项的值;应用setVisibleRowCount(intvisibleRowCount)可以设置JList中可视选项的行数。

选择了JList选项时,将引发ListSelectionEvent事件,通过对JList添加ListSelectionListener事件侦听器来编写响应的事件处理程序。【例6-15】组合框和列表框应用示例。

importjava.awt.*;

importjavax.swing.*;

importjava.awt.event.*;

importjavax.swing.event.*;

publicclassMyJComboBoxJListextendsJFrame

{ String[]comboStrings={"中共党员","共青团员","群众","民主党派"};

String[]listStrings={"书画协会","文学社","篮球协会","电脑协会"};

JTextAreata=newJTextArea(8,20);

JComboBoxcombo=newJComboBox(comboStrings);

JListlst=newJList(listStrings);

JTextFieldtf=newJTextField(10);

JLabeljl1=newJLabel("政治面貌"); JLabeljl2=newJLabel("参加社团");

JLabeljl3=newJLabel("学生姓名");

JPaneljp1=newJPanel();

JPaneljp2=newJPanel();

JPaneljp3=newJPanel();

publicMyJComboBoxJList()

{

combo.addItemListener(newItemListener(){ ta.setText("");

inti=combo.getSelectedIndex();

ta.append("学生姓名:"+tf.getText()+"\n"+"政治面貌是:"+comboStrings[i]);

}

});

lst.addListSelectionListener(newListSelectionListener(){

publicvoidvalueChanged(ListSelectionEvente){

ta.setText(null); ta.append("参加的社团是"+"\n");

Object[]items=lst.getSelectedValues();

for(inti=0;i<items.length;i++)

ta.append((String)items[i]+"\n");

}

});

ta.setEditable(false);

setLayout(newBorderLayout()); jp1.add(jl3);jp1.add(tf);

jp2.add(jl1);jp2.add(combo);

jp3.add(jl2);jp3.add(lst);jp3.add(ta);

add(jp1,BorderLayout.NORTH);

add(jp2,BorderLayout.CENTER);

add(jp3,BorderLayout.SOUTH);

}

publicstaticvoidmain(String[]args)

{ MyJComboBoxJListframe=newMyJComboBoxJList();

frame.setTitle("测试JComboBox&JList");

frame.pack();

frame.setVisible(true);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

运行结果如图6-17所示。图6-17JComboBox和JList的使用例6-15中,学生政治面貌的填写是一个组合框,只能选择四个选项中的一个。当选择了组合框中的选项后,触发组合框事件侦听的响应,即可在右下文本区域框中填写学生的姓名和政治面貌。学生参加社团通过列表框来实现,可以同时选择多个选项,选择后响应其事件并在右下文本区域内填写学生所选择的社团组织。6.5.1菜单

1.菜单JMenu

Java菜单的组成一般是一个菜单条JMenuBar包含多个菜单JMenu,菜单JMenu又包含若干个菜单项JMenuItem,菜单项JMenuItem又分为两个子类JCheckBoxMenuItem和JRadioButtonMenuItem。JcheckBoxMenuItem实现复选框菜单的选项,JRadioButtonMenuItem实现单选菜单的选项。菜单条JMenuBar必须加入到一个支持JMenuBar的容器中去,如JFrame、JDialog和JApplet等。6.5高级Swing组件编程当用户选择某个菜单项时会引发ActionEvent事件,因此,通过添加ActionListener侦听器的方法来处理菜单事件。

【例6-16】菜单的使用。

importjava.awt.*;

importjavax.swing.*;

importjava.awt.event.*;

publicclassMyJMenuextendsJFrame

{

publicMyJMenu()

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论