用 IFrame 跟上潮流.docx
- 文档编号:6842664
- 上传时间:2023-01-11
- 格式:DOCX
- 页数:14
- 大小:150.22KB
用 IFrame 跟上潮流.docx
《用 IFrame 跟上潮流.docx》由会员分享,可在线阅读,更多相关《用 IFrame 跟上潮流.docx(14页珍藏版)》请在冰豆网上搜索。
用IFrame跟上潮流
用IFrame跟上潮流
简介:
IFrame是一种应用程序窗口体系结构,它可以有自定义颜色、自定义边框、自定义形状、自定义组件、甚至透明性。
有了JFrame,就不需要在应用程序中总是使用乏味的、老的JFram了。
在本文中,IT专家MichaelAberethy介绍了IFrame类,并展示了如何用它将标准JFrame应用程序窗口立刻转换为先进的IFrame。
自Java1.0开始,UI开发人员就一直在寻找自定义应用程序窗口的方法。
在引入了Swing后,这个问题愈发突出了,因为开发人员可以创建具有令人惊叹的更复杂的、更高级widget,但是却受到它所在的Frame或者JFrame和它们的特定于操作系统的外观的限制。
常常可以看到应用程序在框架边框内部看起来很好,但是MicrosoftWindows的蓝色标题栏却大刹风景的情况。
更糟的是,应用程序有70年代的Motif外观,但却使用了MicrosoftWindows的颜色光滑渐变的标题栏。
JFrame的外观问题
如图1所示的这些外观问题,展现了UI开发人员所面临的许多问题:
应用程序在各个平台上看起来是不一样的,因为JFrame的属性(标题栏颜色、边框、形状等)无法使用公共外观,它们是特于定操作系统的。
图1.JFrame的外观是如何变化的
Metal外观
Motif外观
Windows外观
解决方案看起来很很明显:
一个独立于操作系统的框架,它具有JFrame提供的所有功能——注册到OS窗口管理器、调整大小/重绘管理、最大化/最小化/恢复,同时又可以设置这些组件的外观。
Java1.3提供了JFrame的功能,但牺牲了定制能力。
在Java1.4中,Sun在Frmae类中引入了一个新的setUndecorated()函数,它走到了另一个极端——它可以自定义框架中的所有内容,但是缺少了Java1.3中大多数特定于操作的好处。
IFrame类是对这个问题的期待已久的解决方案。
通过弥合这两个问题之间的距离,IFrame提供了一个使用简单、同时又很强大的解决方案,可以根据需要对框架进行或多或少的自定义,同时不会牺牲使用JFrame时所习惯的任何特定于操作系统的功能。
不用再守着同样的陈旧的蓝色标题栏、同样的陈旧的三个窗口按钮和同样的陈旧的斜面边框。
虽然对于普通应用程序来说,JFrame仍然很有用,但是有些应用程序需要比它所能提供的更多的功能,如:
∙所有具有自定义外观的应用程序。
∙所有用于体现公司的某种品牌形象的应用程序。
∙所有需要对其窗口具有更多控制的应用程序。
IFrame通过提供一个容易使用的API而突破了JFrame的限制,这个API可以生成具有任何状态的框架、可以有任何颜色和状态的标题栏、可用于更多功能的标题栏按钮、具有任何颜色和大小的边框、按钮旁边的组件和标题栏中的标签及甚至是透明性。
本文介绍IFrame框架。
首先描绘这个体系结构中的每一个类及其作用。
当然,学习如何使用IFrame的最好方法是使用例子,所以我举了四个使用IFrame的应用程序的例子,它们具有不同的复杂性。
阅读了本文及学习IFrame体系结构后,应当能够让应用程序窗口从乏味窗口(图2)变为炫目窗口(图3)。
图2.使用IFrame之前
图3.使用IFrame之后
IFrame体系结构
IFrame体系结构非常容易和直观,这可以从图4展示的类图中看出来。
用于作为应用程序窗口的主类是IFrame。
IFrame包含类IBorderPanel的一个到多个实例,这个类的子类包括IWindowTitleBar和IContentPane。
IBorderPanels通过触发WindowChangeEvents与IFrame通信,IFrame对它进行处理并作出响应。
通过分析体系结构中每一个组件,就会清楚为了定制自己的IFrame,需要在什么地方和什么时候改写默认功能。
图4.IFrame体系结构
IFrame
IFrame是用于创建自定义框架的主类。
除了从IFrame的父类JFrame继承的方法外,IFrame还增加了几个public方法,可以用来改变框架的基本外观组件。
IFrame的默认行为与JFrame一样,所以JFrame和默认IFrame可以互换。
不过,通过调用IFrame中可以使用的几个public方法,可以只用几行代码迅速改变窗口的外观。
注:
在JFrame对应的getContentPane()和setContentPane()的位置上应当使用IFrame的getIContentPane()和setIContentPane()方法。
在IFrame中添加的所有组件都应当调用myIFrame.getIContentPane().add()。
用getContentPane()在IFrame中添加组件或者用setContentPane()设置内容窗格会导致不可预测的、并且很可能是错误的行为。
IBorderComponent
IBorderComponent是在IFrame中加入的所有可以控制Windows的位置和调整大小的JPanel的父类。
乍看之下,最可能的子类是IWindowTitleBar和IContentPane,因为它们看起来是惟一进行调整大小和移动的类。
不过在当前的应用程序中,有许多是用应用程序窗口内的组件调整应用程序窗口大小或者移动它的。
例如,所有MicrosoftOffice应用程序现在都在应用程序窗口右下角有一个小的widget,可以用来调整大小(可以去自己试一试)。
所以如果设计一个包含所有类型的调整大小和移动窗口的widget,那么所要做的就是继承IBorderComponent,这些widget就会具有与用IWindowTitleBar和IContentPane得到的同样的移动和调整大小的能力。
IWindowTitleBar
自定义框架的大部分工作都是在IWindowTitleBar中进行的。
与IFrame一样,IWindowTitleBar有许多public方法,不用继承它或者自己编写方法就可以改变标题栏的属性。
虽然用这些方法可以容易地对外观进行改变,但是所有高级的设计都应当继承IWindowTitleBar以使用paintComponent(),这个方法可以做出更复杂的标题栏。
(关于复杂的标题栏以及它是如何继承IWindowTitleBar的内容,请参阅下面例3。
)
除了改变标题栏的背景颜色,IWindowTitleBar还提供了许多功能,可以用来控制标题栏中的IWindowButtons。
在默认情况下,IWindowTitleBar包含MicrosoftWindows应用程序中可以看到的三个标准窗口按钮,但是可以容易地删除它们或者添加自己的具有不同功能的窗口按钮。
可以改变按钮的大小和颜色,如果创建高级的窗口按钮,那么可以继承IWindowButton以绘制所希望的任何形状和颜色方案(尽管改变JButton的外观超出了本文的范围)。
也许自定义IWindowTitleBar的最有技巧性的方面是管理边框。
在默认情况下,窗口标题栏是标准的矩形边框,但是如果创建一个具有非标准边框的复杂标题栏(请参阅例4),那么必须继承IWindowTitleBar并覆盖isMouseOnBorder()和isInsideTitleBar(),以自己管理边框。
IContentPane
IContentPane提供了在其中加入所有应用程序组件的基本容器,很像JFrame中的JFcontentPane。
因为它也继承了IBorderComponent,所以在默认情况下它也管理自己的边框。
IContentPane边框的默认实现也是矩形。
要想得到非矩形的复杂边框,需要继承IContentPane并通过重载isMouseOnBorder()自己处理边框。
IWindowButton
IWindowButton提供了出现在标准MicrosoftWindowsJFrame标题栏中的三个按钮(最小化、还原和关闭)的默认实现,但是它们还为想要在标题栏中创建和添加的所有自定义窗口按钮提供了基类。
如果希望在标题栏中加入第四个按钮(如果认为自己比Microsoft更了解情况),那么可以继承IWindowButton并重载paintComponent()。
不过,对于创建自定义按钮的介绍不在本文的范围之内。
WindowChangeEvent/WindowChangeListener
Swing为窗口中会发生的几乎所有事情提供了事件。
有大约15种事件和处理窗口事件的相应方法。
但是,就算有了所有这些事件,Swing也没有包括窗口可以生成的所有事件,最明显的是特定于操作系统的事件。
最后,使用WindowChangeEvent和WindowChangeListener类,可以确保接收窗口会发生的所有事件。
WindowChangeEvent处理所有窗口变化的情况(因而类的名字变化)。
它可以改变其大小、在屏幕上定位、恢复状态或者最小化/最大化状态。
将这五个事件加上15种已有的事件,就包括了所有基本情况。
现在窗口中发生的所有事情都可以掌握了。
例子
现在可以编写几行代码并改变应用程序窗口的整个外观、亲自体验IFrame的强大功能了。
记住,IFrame可以很简单,也可以很复杂,完全取决于您的需要。
在这一节,我将完成几个展示开始使用IFrame所需要完成的基本步骤的例子。
学习这些例子并在自己的计算机中运行它们,会看到仅凭阅读说明或者API所想像不到的效果。
运行所有四个例子并分析每个例子的代码,我相信您将会理解为什么IFrame可以成为应用程序中一个强大的工具。
所有例子都包含在com.ibm.iwt.examples包中,可以从参考资料main()方法。
它们是用JDK1.4编写的。
例1:
默认IFrame
为了保持IFrame“向后兼容”,我让IFrame的默认实现看上去与JFrame的完全一样,如图5所示:
图5.默认IFrame
因为IFrame不从本机操作系统中得到其信息,所以我只能选择一种操作系统进行模拟。
默认的IFrame实现看起来就像在MicrosoftWindows2000中的JFrame一样,我们就保持使用它了。
如果在Windows2000计算机中运行应用程序,那么将可以互换JFrame与IFrame,不会有看得出来的差别。
如果运行的不是Windows2000--那么,第一个练习应用程序可以是模拟自己的操作系统。
清单1显示了创建一个IFrame是多么容易:
清单1.IFrame例1
publicTestApp1()
{
setTitle("Window");
}
是的,就是这么容易(想象一下如果所有应用程序开发都这么容易,那该会怎样)。
建议用法:
在希望向后兼容JFrame时。
例2:
改变默认颜色、边框和大小
现在看一些更有意思的代码。
在这个例子中,我将标题栏框架周围的边框的背景颜色改为红色,改变窗口按钮的颜色、还改变了标题栏和窗口按钮的大小。
图6显示了在例2中创建的IFrame。
图6.改变颜色、边框和大小
仅就所说的这些改变,可以看出它们在JFrame中都是不可能的,但是用IFrame就可以很容易地实现。
清单2显示了如何创建例2中使用的IFrame:
清单2.IFrame例2
publicTestApp2()
{
IWTUtilities.setBorderSize(newInsets(3,3,3,3));
setIContentPaneBorder(newLineBorder(Color.red,3));
setTitleBarHeight(35);
setTitleBarBackground(Color.red);
setTitleBarButtonColors(Color.red,Color.white);
setTitleBarButtonSize(newDimension(26,26));
setTitle("Window");
}
这样就行了。
改变框架的外观所要做的就是这些。
尽管这只是IFrame的一个基本的例子,只使用了六行代码,但是我们完成了一些UI开发人员多年来一直想要做的事情。
这个基本的例子已经比当前使用的应用程序窗口中的99%都更先进。
建议用法:
如果希望迅速改变框架的外观,同时又不想使它与特定于操作系统的框架有大的改变时使用。
例3:
利用IWindowTitleBar的子类
如果希望做比颜色、大小和标题栏中的按钮这样的基本改变更多的事情,就必须继承IWindowTitleBar类以充分利用它提供的各种可能性。
创建了子类后,就可以对标题栏做很多新的操作了,包括更高级的绘制选项以及更强大的、在标题栏中加入任何组件的能力。
为什么让标题栏中的按钮和标签把自己限制住呢?
加上一直想要的JTable吧。
只要调用IFrame中的setTitleBar(),就可以创建一个应用程序开发史上最先进的标题栏子类,并在任何IFrame上使用它。
图7描绘了创建自定义窗口组件所可能产生的外观:
图7.创建自定义窗口组件
在这个例子中,通过建立清单2中的框架,并用一个新的、动态的边框取代单调的、静态的红色标题栏,充分利用了所有这些新的可能性。
可以从图中看到,标题已经从左边移到了中间,并使用了更有可读性的字体。
我用一个在左边的“关闭”按钮取代右边三个标准按钮。
最后,也许是最有创造性的,我在标题栏的右边增加了一个JSlider,可以让这个IFrame的用户动态改变标题栏背景的渐变色。
清单3中的代码片段显示了将例2转变为例3所需要的额外代码。
这些对于JFrame来说是不可能的。
清单3.IFrame例3
publicTestApp3()
{
IWTUtilities.setBorderSize(newInsets(3,3,3,3));
getIContentPane().setBorder(newLineBorder(Color.red,3));
setTitleBar(newTitleBar());
}
privateclassTitleBarextendsIWindowTitleBarimplementsChangeListener
{
privateColorc=newColor(0,0,0);
privateJSliderslider;
publicTitleBar()
{
setPreferredSize(newDimension(0,26));
removeWindowDecorations();
addWindowButton(IWindowButton.CLOSE,SwingConstants.LEFT);
setWindowButtonColors(Color.RED,Color.WHITE);
addTitle(getTitle(),SwingConstants.CENTER,
newFont("Verdana",Font.BOLD,14),Color.WHITE);
slider=newJSlider();
add(slider,newGroupFlowLayoutConstraints(SwingConstants.RIGHT,
newInsets(3,3,3,3)));
slider.addChangeListener(this);
slider.setMaximum(255);
slider.setMinimum(0);
slider.setOpaque(false);
}
publicvoidpaintComponent(Graphicsg)
{
super.paintComponent(g);
PaintUtilities.paintGradient(g,0,0,getWidth(),getHeight(),c,Color.WHITE,
SwingConstants.HORIZONTAL);
}
publicvoidstateChanged(ChangeEvente)
{
c=newColor(slider.getValue(),0,0);
repaint();
}
}
分析创建这个IFrame的代码,可以看到它不比清单2中的代码更复杂。
不过,出于下面两个理由,我将所有代码移到了IWindowTitleBar的子类中:
∙通过重载IWindowTitleBar中的paintComponent()提供外观更精致的标题栏
∙加入动态改变标题栏背景颜色的JSlider
因为可以在任何位置上添加任何JComponent,所以在为标题栏创建新widget时可以尽情发挥想象力。
对于在标题栏中创建新功能这方面来说,改变背景颜色的JSlider只是冰山的一角。
可以开发出许多在标题栏中使用的有创造性的自定义组件。
建议用法:
适合使用IWindowTitleBar的子类的情况有:
∙希望在标题栏中创建更复杂的图像,而不是一种单纯的颜色
∙常常会希望动态改变框架的标题栏属性,并且不希望每改变次它们时调用多个函数
∙希望在标题栏中加入默认组件以外的其他组件
例4:
结合在一起并加上透明性
最后一个例子将其他例子结合到一起并加入了IFrame的最新特性——透明性。
这个例子是最复杂的,并且很好地体现了IFrame在用最少的工作创建具有出色外观的应用程序窗口方面的强大能力。
图8显示了具有某种透明性的复杂应用程序窗口,这种透明性使它区别其他应用程序窗口。
图8.加入透明性
首先,让我们介绍一下透明性。
几年前,MicrosoftWindows应用程序开始有了标准矩形以外的框架。
其中使用最多的就是WindowsMediaPlayer,从那之后,使应用程序具有非矩形形状就成了一种趋势和很酷的事情。
是的,Java应用程序一直没有这种能力,并且在透明性方面总是差强人意,特别是当与本机绘制像素交互时。
幸运的是,IFrame改变了这种局面,可以开发具有透明性、甚至对于本机绘制像素透明的应用程序窗口。
IFrame中的setTransparent()在指定的边界内绘制指定的组件透明性。
在大多数情况下,组件将是IWindowTitleBar或IContentPane的子类。
应当在子类的paintComponent()中调用setTransparent(),以使它可以用它下面的正确像素重绘。
最后提醒一下,绘制透明性速度相对来说是慢的,应当尽可能使透明区域相对较小。
最后这个例子使用了IFrame的其他更高级的功能。
从清单8中可以看到,标题栏不再是标准的矩形标题栏了。
它是自定义的形状,具有完全不同于矩形的边框。
因此,在所创建的IWindowTitleBar子类中,必须重载isMouseOnBorder()和isInsideTitleBar()方法,以使标题栏在绘制光标时具有正确的行为,并可以调整大小。
清单4显示了生成例4中看到的应用程序窗口所需要的代码。
清单4.IFrame例4
publicTestApp4()
{
setTitle("Window");
IWTUtilities.setBorderSize(newInsets(0,7,7,7));
IWTUtilities.setDiagonalSize(20);
getIContentPane().setBorder(newAppBorder());
getIContentPane().setBackground(newColor(255,255,102));
setTitleBar(newTitlePanel());
}
privateclassTitlePanelextendsIWindowTitleBar
{
publicTitlePanel()
{
setPreferredSize(newDimension(800,35));
setFont(newFont("Verdana",Font.BOLD,22));
removeWindowDecorations();
}
protectedbooleanisInsideTitleBar(intx,inty)
{
if(x<(int)getWidth()*.1||x>(int)getWidth()*.9)
returnfalse;
returntrue;
}
protectedvoidisMouseOnBorder(intx,inty)
{
if(y>10&&y>16&&!
isInsideTitleBar(x,y))
isMouseOnBorder=true;
else
isMouseOnBorder=false;
}
publicvoidpaintComponent(Graphicsg)
{
super.paintComponent(g);
//...paintcodehere
setTransparent(this,g,0,0,w+1,10);
PaintUtilities.paintDropShadow(g,(int)(w*.1),0,(int)(w*.8),27);
Colorc1=newColor(67,118,135);
Colorc2=newColor(105,152,199);
PaintUtilities.paintGradient(g,(int)(w*.1),0,(int)(w*.9),14,c1,c2);
PaintUtilities.paintGradient(g,(int)(w*.1),14,(int)(w*.9),13,c2,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- IFrame 跟上潮流 跟上 潮流