第10章 Swing组件概述.docx
《第10章 Swing组件概述.docx》由会员分享,可在线阅读,更多相关《第10章 Swing组件概述.docx(22页珍藏版)》请在冰豆网上搜索。
第10章Swing组件概述
模块十Swing组件概述
1.Swing概述
Java1.0刚出现时,包含一个用于基本GUI编程的类库,Sun把它叫做抽象窗口工具箱(AbstractWindowToolkit,AWT).基本AWT库处理用户界面元素的方法是把这些元素的创建和行为委托给每个目标平台(Windows,Solaris,Macintosh等)上的本地GUI工具进行处理。
不同平台的AWT用户界面存在着不同的bug。
程序员们必须在每一个平台上测试他们的应用程序,他们因此嘲笑AWT是“一次编写,到处调试”。
在1996年,Netscape开发了一个工作方式完全不同的GUI库,他们把它叫做IFC(InternetFoundationClasses,因特网基础类集)。
用户界面元素,如按钮,菜单等,是绘制到空白窗口上的。
因此,Netscape的IFC部件在程序运行的所有平台上看起来都一样。
Sun和Netscape合作完善了这种方法,创建了一个新的用户界面库,它的代码名是“Swing”(有时也叫作“Swing集”)。
从此才真正实现了“一次编写,到处运行”的口号。
另外,Swing只是提供了更好的用户界面组件而已。
AWT的基本体系结构,尤其是事件处理模型,从Java1.1版后并没有改变。
Swing有以下的优势:
1,Swing具有更丰富,更方便的用户界面元素集合。
2,Swing对低层平台的依赖更少;因此和平台有关的bug也少的多。
3,Swing给不同平台上的用户一致的感觉。
2.创建框架
Java中的顶层窗口(即:
那些没有包含在其他窗口中的窗口)被称为框架。
例如:
SimpleJFrameTest.java
importjavax.swing.*;
publicclassSimpleJFrameTest
{
publicstaticvoidmain(String[]args)
{
SimpleJFramefram=newSimpleJFrame();
fram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fram.show();//fram.setVisible(true);
}
}
classSimpleJFrameextendsJFrame
{
publicstaticfinalintWIDTH=400;
publicstaticfinalintHEIGHT=300;
publicSimpleJFrame()
{
setSize(WIDTH,HEIGHT);
}
}
注解:
大部分Swing组件类的名字都是以“J”开头,如JButton,JFrame,JTextField等等。
Java中也有着Button,Frame类,不过它们都是AWT组件。
如果你不小心忘了写Swing组件前的“J”,程序还是很可能能够编译和运行,不过由于混杂了Swing和AWT组件,在视觉和响应上可能会有不一致的地方。
3.给框架定位
JFrame类本身只有几个用来改变框架外观的类。
当然,通过继承,JFrame从不同的超类中继承来很多用于处理框架大小和位置的方法。
下面列出几个可能最为重要的方法:
●dispose方法----关闭窗口并收回用于创建窗口的任何资源;
●setIconImage方法----当窗口最小化时,把一个Image对象用作图标。
●setTitle方法-----改变标题栏中的文字。
●setResizable方法—使用boolean参数来决定框架大小是否能被用户改变。
●setLocation方法----用来显示组件在容器中的位置(对于框架来说,方法中的参数坐标是相对于整个屏幕而言的,对于容器内的组件,坐标是相对于容器的)。
●setBounds方法----同上,只不过它带有四个参数(其中前两个参数同上,都是设置组件的位置,后两个参数用来设置组件的大小)。
●Toolkit工具的介绍
4.在面板中显示信息
JFrame与Frame不同的是,在JFrame中加组件是加在内容窗格里的。
如:
ContainercontentPane=frame.getContentPane();//用上例中的frame对象
JComponentc=…;
contentPane.add(c);
如果你只需要在框架中显示一个Swing组件,那么你可以用下面的方式把组件放置到内容窗格中。
Frame.setContentPane(c);
面板是也是个容器。
它可以再放其他的组件,我们可以设计自己的面板:
✧定义一个扩展JPanel的新类
✧覆盖paintComponent方法
注意:
paintComponent方法实际上定义在JComponent中,这个类是所有非窗口Swing组件的父类。
该方法有一个Graphics类型的参数。
Graphics对象存储了一个用于绘制图形和文本的设置集合(比如字体和当前颜色)。
Java中的所有绘制都必须用Graphics对象。
它拥有绘制,图案,图象和文本的方法。
例如:
SimpleJFrameTest.java
importjavax.swing.*;
importjava.awt.*;
publicclassSimpleJFrameTest
{
publicstaticvoidmain(String[]args)
{
SimpleJFramefram=newSimpleJFrame();
fram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fram.show();//fram.setVisible(true);
}
}
classSimpleJFrameextendsJFrame
{
publicstaticfinalintWIDTH=400;
publicstaticfinalintHEIGHT=300;
publicSimpleJFrame()
{
setSize(WIDTH,HEIGHT);
ContainercontentPane=getContentPane();
contentPane.add(newJPanelOne());
}
}
classJPanelOneextendsJPanel
{
publicvoidpaint(Graphicsg)
{
super.paint(g);
g.fillRect(30,10,200,100);
g.clearRect(60,30,80,40);
g.drawRect(70,45,35,20);
g.drawLine(10,60,250,60);
}
}
5.Graphics2D图形
上面简单介绍了Graphics的基本用法,下面来介绍2D图形的基本用法:
Java中的绘图采用三步法:
◆用setColor(),setFont(),setPaintMode()和setXORMode()之类的方法指定绘图属性
◆标识要画的形体
◆绘制
Graphics2D中的绘图也用三步法。
但形体的标识和绘制有所不同。
一般来说,指定要画的形体时要生成一个实现Shape接口的对象。
例如:
Arc2D(画圆弧),Line2D,Rectangle2D,RoundRectangle2D,Ellipse2D,都放在java.awt.geom包中。
一旦标识要画的形体,就要开始画了。
这是用三个Graphics2D方法完成的:
clip(),draw()或者fill(),都取Shape对象为参数。
●clip()方法将绘图区缩小到指定形体与当前剪取区相交部分,影响后面的绘图操作。
●draw()方法用当前Stroke(笔划)绘制Shape的外形。
●fill()方法用当前Paint模式填充Shape.
例如:
SimpleJFrameTest.java
importjavax.swing.*;
importjava.awt.*;
importjava.awt.geom.*;
publicclassSimpleJFrameTest
{
publicstaticvoidmain(String[]args)
{
SimpleJFramefram=newSimpleJFrame();
fram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fram.show();//fram.setVisible(true);
}
}
classSimpleJFrameextendsJFrame
{
publicstaticfinalintWIDTH=400;
publicstaticfinalintHEIGHT=300;
publicSimpleJFrame()
{
setSize(WIDTH,HEIGHT);
ContainercontentPane=getContentPane();
contentPane.add(newJPanelTwo());
}
}
classJPanelTwoextendsJPanel
{
publicvoidpaint(Graphicsg)
{
Graphics2Dg2d=(Graphics2D)g;
g2d.setColor(Color.blue);
GeneralPathrectangle=newGeneralPath(GeneralPath.WIND_EVEN_ODD);
rectangle.moveTo(20f,40f);
rectangle.lineTo(120f,40f);
rectangle.lineTo(120f,80f);
rectangle.lineTo(20f,80f);
rectangle.closePath();
Arc2Darc=newArc2D.Double(90,40,90,40,270,180,Arc2D.CHORD);
//Drawshape
g2d.fill(rectangle);
g2d.draw(arc);
}
}
渐变填充图形
例如:
SimpleJFrameTest.java
importjavax.swing.*;
importjava.awt.*;
importjava.awt.geom.*;
publicclassSimpleJFrameTest
{
publicstaticvoidmain(String[]args)
{
SimpleJFramefram=newSimpleJFrame();
fram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fram.show();//fram.setVisible(true);
}
}
classSimpleJFrameextendsJFrame
{
publicstaticfinalintWIDTH=400;
publicstaticfinalintHEIGHT=300;
publicSimpleJFrame()
{
setSize(WIDTH,HEIGHT);
ContainercontentPane=getContentPane();
contentPane.add(newJPanelThree());
}
}
classJPanelThreeextendsJPanel
{
publicvoidpaint(Graphicsg)
{
Graphics2Dg2d=(Graphics2D)g;
GradientPaintgp=newGradientPaint(25,45,Color.cyan,75,95,Color.BLUE);
g2d.setPaint(gp);
Rectangle2Drectangle=newRectangle2D.Double(0,20,100,100);
g2d.fill(rectangle);
gp=newGradientPaint(150,45,Color.cyan,200,95,Color.blue,true);
g2d.setPaint(gp);
rectangle=newRectangle2D.Double(125,20,100,100);
g2d.fill(rectangle);
Point2Dp2d1=newPoint2D.Float(45,170);
Point2Dp2d2=newPoint2D.Float(195,220);
gp=newGradientPaint(p2d1,Color.cyan,p2d2,Color.blue,false);
g2d.setPaint(gp);
Arc2Darc=newArc2D.Double(20,145,200,100,45,300,Arc2D.PIE);
g2d.fill(arc);
g.setColor(Color.black);
g.drawLine(25,45,75,95);
g.drawLine(150,45,200,95);
g.drawLine(45,170,195,220);
}
}
1.容器布局(ContainerLayout)
容器中组件的布局通常由布局管理器控制。
每个Container(比如一个Panel或一个Frame)都有一个与它相关的缺省布局管理器,它可以通过调用setLayout()来改变。
布局管理器负责决定布局策略以及其容器的每一个子组件的大小。
1.1.布局管理器
Java编程语言包含下面的布局管理器:
-FlowLayout—Panel和Applets的缺省布局管理器
-BorderLayout—Window、Dialog及Frame的缺省管理程序
-GridLayout
-CardLayout
-GridBagLayout
GridBag布局管理器在本模块中不深入讨论。
下图阐述了容器的默认布局管理器
1.2.FlowLayout的一个简单例子
这个样板代码阐述了几个要点,将在下一节讨论。
1.importjava.awt.*;
2.
3.publicclassExGui{
4.privateFramef;
5.privateButtonb1;
6.privateButtonb2;
7.
8.publicstaticvoidmain(Stringargs[]){
9.ExGuiguiWindow=newExGui();
10.guiWindow.go();
11.}
12.
13.publicvoidgo(){
14.f=newFrame("GUIexample");
15.f.setLayout(newFlowLayout());
16.b1=newButton("PressMe");
17.b2=newButton("Don'tPressMe");
18.f.add(b1);
19.f.add(b2);
20.f.pack();
21.f.setVisible(true);
22.}
23.}
这段代码会生成如下界面:
图10-5
1.2.1.main()方法
本例中第8行main()方法有两个作用。
首先,它创建了ExGui对象的一个实例。
回想一下,直到一个实例存在,还没有被称做f,b1和b2的真实数据项可以使用。
第二,当数据空间被创建时,main()在该实例的上下文中调用实例方法go()。
在go()中,真正的运行才开始。
1.2.2.newFrame(“GUIExample”)
这个方法创建Java.awt.Frame类的一个实例。
根据本地协议,在Java编程语言中,Frame是顶级窗口,带有标题条,在这种情况下,标题条由构造函数的参数“GUIExample”定义,此时Frame是不可见的,大小为零。
1.2.3.f.setLayout(newFlowLayout())
这个方法创建Flow布局管理器的一个实例,并将它安装在框架中。
Frame默认的布局管理器是BorderLayout,但本例中没有使用。
Flow布局管理器在AWT中是最简单的,它在某种程度上象一个页面中的单词被安排成一行一行的那样来定位组件。
请注意,Flow布局缺省地将每一行居中。
1.2.4.newButton(“PressMe”)
这个方法创建Java.awt.Button类的一个实例。
按钮是从本地窗口工具包中取出的一个标准按钮。
按钮标签由构造函数的参数字符串定义。
1.2.5.f.add(b1)
这个方法告诉框架f,它将包容组件b1。
b1的大小和位置受从这一点向前的Frame布局管理器的控制。
1.2.6.f.pack()
这个方法告诉框架来设定大小,能恰好密封它所包含的组件。
1.2.7.f.setVisible(true)
这个方法使框架以及其所有的内容变成用户看得见的东西。
2.布局管理器
2.1.FlowLayout
前面所用的FlowLayout布局管理器对组件逐行地定位。
每完成一行,一个新行便又开始。
与其它布局管理器不一样,FlowLayout布局管理器不限制它所管理的组件的大小,而是允许它们有自己的最佳大小。
Flow布局构造程序参数允许将组件左对齐或右对齐(缺省为居中)。
如果想在组件之间创建一个更大的最小间隔,可以规定一个界限。
当用户对由Flow布局管理的区域进行缩放时,布局就发生变化。
如:
下面的例子就是如何用类容器的setLayout()方法来创建Flow布局对象并安装它们。
setLayout(newFlowLayout(intalign,inthgap,intvgap));
align的值必须是FlowLayout.LEFT,FlowLayout.RIGHT,或FlowLayout.CENTER。
例如:
setLayout(newFlowLayout(FlowLayout.RIGHT,20,40));
下述程序构造并安装一个新Flow布局,它带有规定好的对齐方式以及一个缺省的5单位的水平和垂直间隙。
setLayout(newFlowLayout(FlowLayout.LEFT));
下述程序构造并安装一个新Flow布局,它带有规定好的居中对齐方式和一个缺省的5单位的水平和垂直间隙。
setLayout(newFlowLayout());
下面的代码将几个按钮添加到框架中的一个Flow布局中:
importjava.awt.*;
publicclassMyFlow{
privateFramef;
privateButtonbutton1,button2,button3;
publicstaticvoidmain(Stringargs[]){
MyFlowmflow=newMyFlow();
mflow.go();
}
publicvoidgo(){
f=newFrame("FlowLayout");
f.setLayout(newFlowLayout());
button1=newButton("Ok");
button2=newButton("Open");
button3=newButton("Close");
f.add(button1);
f.add(button2);
f.add(button3);
f.setSize(100,100);
f.setVisible(true);
}
}
2.2.BorderLayout
BorderLayout布局管理器为在一个Panel或Window中放置组件提供一个更复杂的方案。
BorderLayout布局管理器包括五个明显的区域:
东、南、西、北、中。
北占据面板的上方,东占据面板的右侧,等等。
中间区域是在东、南、西、北都填满后剩下的区域。
当窗口垂直延伸时,东、西、中区域也延伸;而当窗口水平延伸时,东、西、中区域也延伸。
BorderLayout布局管理器是用于Dialog和Frame的缺省布局管理器。
下面这一行构造并安装一个新Border布局管理器,在组件之间没有间隙:
setLayout(newBorderLayout());
这一行构造并安装一个Border布局,在组件之间有由hgap和vgap规定的间隙:
setLayout(newBorderLayout(inthgap,intvgap);
在布局管理器中组件必须被添加到指定的区域,而且还看不见。
区域名称拼写要正确。
可以使用Border布局管理器来产生布局,且带有在缩放时在一个方向、另一方向或双方向上都延伸的元素。
如果离开一个Border布局未使用的区域,,好象它的大小为0。
中央区域即使在不含组件的情况下仍然呈现为背景。
可以仅将单个组件添加到Border布局管理器五个区域的每一个当中。
如果添加不止一个,只有最后一个看得见。
后面的模块将演示如何用中间容器来允许不止一个组件被放在单个Border布局管理器区域的空间里。
下面的代码对前例进行了修改,表示出了Border布局管理器的特性。
可以用从Container类继承的setLayout()方法来将布局设定为Border布局。
1.importjava.awt.*;
2.
3.publicclassExGui2{
4.privateFramef;
5.privateButtonbn,bs,bw,be,bc;
6.
7.publicstaticvoidmain(Stringargs[]){
8.ExGui2guiWindow2=newExGui2();
9.guiWindow2.go();
10.}
11.
12.publicvoidgo(){
13.f=newFrame("BorderLayout");
14.bn=newButton("B1");
15.bs=newButton("B2");
16.be=newButton("B3");
17.bw=newButton("B4");
18.bc=newButton("B5");
19.
20.f.add(bn,BorderLayout.NORTH);
21.f.add(bs,BorderLayout.SOUTH);