使用Xkins为Web应用增加皮肤<o:p></o:p>
——为你的Web应用增加换肤能力<o:p></o:p>
原文出处:http://www.javaworld.com/javaworld/jw-10-2004/jw-1025-xkins.html <o:p></o:p>
注:图片请参看原文。 摘要<o:p></o:p>
在这篇文章中,Guillermo Meyer说明了为Web应用换肤的过程,解释了如何一种管理皮肤的框架——Xkins来为你的应用换肤。Xkins可以和其他的UI框架,如Struts和Titles等,一起使用。这里Meyer将和你一起时实现一个需要两个皮肤的例子,同时介绍如何给它添加唯一的皮肤。<o:p></o:p>
<o:p></o:p>
皮肤指用户界面的外观,它为Web应用带来不同的视觉感受。当用户单击按钮以后,皮肤改变了用户界面,但是并不改变UI的动作。皮肤的更换导致应用外观的改变,但是为了达到这种改变,Web应用必须懂得如何使用皮肤。<o:p></o:p>
为什么你需要首先为Web应用增加皮肤呢?关于使用皮肤,可能有很多目的,但是这些目的都不是必须的。在一个简单的应用里面,增加皮肤会不合算,但是在一些情况下,你必须用皮肤来处理。这些情况是:<o:p></o:p>
l 当皮肤是系统需要:当用户可以选择个性化的皮肤,甚至创建个性化的皮肤时。<o:p></o:p>
l 当你想给企业组件框架增加皮肤能力:如果你为不同的客户端创建了不同的解决方案,你可以重用所有的组件(标签库)。如果你的组件用皮肤能力,只需要简单改变每个客户端的皮肤而已。<o:p></o:p>
l 当依照一个特定的商业情形需要增加一个不同的皮肤:例如,在一个市场或跨银行的应用中,不同的人群在同一个系统中工作,你需要依据用户群体的图片来修饰你的应用。<o:p></o:p>
为Web应用增加皮肤不是一个容易的任务。你可以使用层叠样式表来改变图片的路径,但是你会被CSS的能力所限制。如果你有一个在每个皮肤中看起来根本不同的组件,也就是说,在每个皮肤中HTML不同,CSS将无法帮你。然而,如果就是简单改变格式就可以解决你的问题,你就可以使用CSS。<o:p></o:p>
一个创建皮肤的好办法就是,限定用户界面的每个部分,然后将每部分结合起来组成完整的界面。例如,如果在皮肤A中你有一个简单表格构成的界面组件,在皮肤B中是一个具有页眉、页脚、图片甚至声音的复杂表格,为每个皮肤结构将生成不同的HTML(很多<tr>和<td>标签)。作为一个例子,让我们假如在皮肤A中,必须产生一个代表标签的HTML:<o:p></o:p>
<p>This is my Label</p><o:p></o:p>
在皮肤B中,标签将这样生成:<o:p></o:p>
<table background="/images/tablebg.gif"><o:p></o:p>
<tr><o:p></o:p>
<td bgcolor="#0000FF"><o:p></o:p>
</td><o:p></o:p>
<td background="/images/cellbg.gif"><o:p></o:p>
This is my Label<o:p></o:p>
</td><o:p></o:p>
<td bgcolor="#0000FF"><o:p></o:p>
</td><o:p></o:p>
</tr><o:p></o:p>
</table><o:p></o:p>
这样你可以发现,这两个UI在每个皮肤中完全不同。它们具有相同的信息(This is my Label),但是是用不同的HTML标记表达的。这个功能CSS不能单独完成。可能使用XML转换或者XSL可以完成。或者你可以使用Xkins。<o:p></o:p>
l 什么是Xkins<o:p></o:p>
Xkins是一种为Web应用管理皮肤的框架。在早期的服务器端Java编程中,你需要在servlet中手动输入HTML。接着,JSP(Java Server Pages)的出现,你可以在Java代码以外书写HTML。现在,我们在Java代码中使用具有HTML标签的标签库时,遇到了同样的问题。使用Xkins,你可以把使用一个新增的而且是非常有用的特性——皮肤,把HTML书写在代码的外边。更多的细节,可以查看Xkins的主页。 <o:p></o:p>
图1 Xkins在Web应用中的位置<o:p></o:p>
<v:shapetype o:spt="75" coordsize="21600,21600" id="_x0000_t75" stroked="f" filled="f" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path gradientshapeok="t" o:extrusionok="f" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype><o:p></o:p>
通过标签使用Xkins和Struts的Web应用,遵循如下的生命周期:<o:p></o:p>
n Struts使用Xkins插件初始化Xkins<o:p></o:p>
n Struts控制器接收HTTP请求<o:p></o:p>
n Struts执行方法,定向到JSP页面显示<o:p></o:p>
n JSP页面使用标签库显示页面<o:p></o:p>
n 标签库通过Xkins外壳——XkinProcessor使用Xkins<o:p></o:p>
n XkinProcessor获得用户皮肤和标签指令代表的模板<o:p></o:p>
n XkinProcessor使用TemplateProcessor和模板关联<o:p></o:p>
n TemplateProcessor显示组成皮肤的UI各部分的类,TemplateProcessor可以使用Velocity、JBYTE (Java By Template Engine)、Groovy或者其他模板引擎来显示输出。<o:p></o:p>
n TemplateProcessor使用皮肤中的资源(元素和路径),返回模板处理好的标签。<o:p></o:p>
n 模板处理好的标签传输给浏览器进行显示<o:p></o:p>
Xkins地址皮肤依据以下的基础原则进行管理:<o:p></o:p>
n 在Java代码以外产生HTML:标签就是产生HTML代码,改变这些代码需要改变Java代码和重新部署应用。Xkins允许你以将产生的HTML放置在自定义的文件(XML文件)中。另外,Xkins允许你将HTML格式标签放置在JSP页面以外,以便以后扩展应用的视觉感受。<o:p></o:p>
n 定义皮肤结构:模板、资源和路径组成一个皮肤。资源可以是一个常数,也可以是像图片和CSS文件之类的元素。定义路径可以帮你组织你的皮肤文件。定义模板可以重用应用中的UI部分。<o:p></o:p>
n 允许扩展Xkins框架:你可以根据自己的需要,使用自己的模板语言来扩展Xkins。例如,如果你需要产生图片,你可以实现一个产生图片的模板处理器。Xkins的模板处理是基于Velocity和JBYTE的。例如,如果你倾向于使用Groovy,你可以创建一个Groovy模板处理器来处理你的UI部分。<o:p></o:p>
n 将UI划分成基本元素:在Xkins中,你可以分离所有的UI组件,创建一个模板。通过这种方式,你可以重用各个部分和改变其中的任何部分使得皮肤显得不同。<o:p></o:p>
n 使用继承减少皮肤的维护:在Xkins中,一个皮肤可以继承其它的皮肤,使用继承皮肤中的所有模板、路径和资源。这样,就可以减少模板的维护。<o:p></o:p>
n 使用合成来创造皮肤:作为继承的延伸,Xkins允许用户合成,以减少维护和增加模板的重用。由于这些特性,用户可以通过从已有的皮肤中选择不同的UI部分来创建自己个性化的皮肤。<o:p></o:p>
n 定义皮肤类型:使用皮肤类型,你可以确定在Xkins实例中的所有皮肤至少有一个和这个类型具有相同的模板。皮肤类型是在一个Xkins实例中所有其它皮肤都唯一的皮肤。在此,皮肤实例是指在Web应用中被一起导入的一组皮肤。<o:p></o:p>
Xkins提供的最大好处就是,所有的HTML都存在一个地方,如果你需要改变的话,只需要简单的修改模板即可。比如,如果你的页面文件过大,发现生成的过多HTML的位置或者那些图片可以被分离,接着改变模板来较少页面文件的大小。你也可以为那些网络速度慢的用户提供一个轻量级的皮肤,为宽带用户提供重量级的。<o:p></o:p>
注意:你可以将Xkins和CSS一起使用。事实上,CSS是因为字体类型和颜色才被推荐使用的,因为重用CSS文件可以避免每次明确的指出字体的外观,从而降低了文件的大小。<o:p></o:p>
在Web应用中,皮肤可以压缩成一个简单的文件(zip文件)以便容易部署。如果你定义了皮肤类型,如果第三方的皮肤符合你声明的皮肤类型,也可以添加到你的Web应用中。<o:p></o:p>
你可以以多种方式来使用Xkins,但是将Xkins和标签库一起使用是Web应用中最好的方式。你可以使用这些标记来生成你的页面,或者装饰已有的标记。<o:p></o:p>
l 定义皮肤<o:p></o:p>
这里有一些定义皮肤的提示:<o:p></o:p>
n 决定皮肤颜色;使用全局常量,以便其它皮肤可以继承和覆盖它们。<o:p></o:p>
n 为每个标签库创建可重用的模板。<o:p></o:p>
n 使用可以被继承的皮肤覆盖的元素来创建模板,这样整个模板不需要为了改变UI外观而重写。<o:p></o:p>
n 为你的Web应用创建一个基础的皮肤,使用它作为你的Xkins实例的类型。<o:p></o:p>
n 避免将HTML写在Java代码内部。如果你有一个包含HTML代码的标签库、servlet、甚至一个JSP页面,可以考虑将HTML移植到Xkins模板里面。<o:p></o:p>
l 示例<o:p></o:p>
现在我们来看一下,在一个需要皮肤管理的简单Web应用中,定义、设计、开发和部署Xkins的操作。在这个例子中,我们实现一个为两个在线书店——Amazing和Barnie & Nibble实现注册用户的简单应用。这个应用将在两个站点中使用(通过框架、portlet或者书店选择的其它格式),但是必须为每个书店提供特定的外观。<o:p></o:p>
为了实现我们的应用,我们遵循如下步骤:<o:p></o:p>
1、 获得包含每个皮肤的HTML页面。<o:p></o:p>
2、 确定皮肤模板。<o:p></o:p>
3、 创建皮肤。<o:p></o:p>
4、 使用皮肤。<o:p></o:p>
5、 部署Web应用。<o:p></o:p>
l 获得包含每个皮肤的HTML页面<o:p></o:p>
首先,我们获得每个书店提供的图形页面设计。这些素材可能是页面原型,必须包含应用中所有可能的页面元素(在我们的例子中,只是一个页面)。如图2和图3。<o:p></o:p>
<o:p></o:p>
图2 Amazing的外观<o:p></o:p>
<o:p></o:p>
图3 Barnie & Nibble的外观<o:p></o:p>
和我们看到的一样,两个页面具有不同的颜色、图片和布局。另外,信息收集器不同,加上Amazing的按钮是GIF格式,而Barnie&Nibble的是一个带格式的HTML按钮。<o:p></o:p>
l 确定皮肤模板<o:p></o:p>
现在我们必须整理页面部分来为我们的应用生成一些模板。我们可以从零开始,或者我们可以在一个用来创建表单的简单皮肤的基础上来分解我们的HTML。基础皮肤以Xkins表单标签的形式存在于Xkins框架中。Xkins表单是一个使用Xkins为Web应用产生表单的标签库实现。<o:p></o:p>
基础皮肤定义了框架(frame)、字段、按钮等等。我们应该使用这个皮肤,同时添加我们项目需要的模板(例如频道)。这个基础皮肤也允许我们使用Xkins表单标签产生我们的JSP页面。<o:p></o:p>
下面让我们看一下我们需要的模板列表:<o:p></o:p>
n frame:包含整个表单的表格<o:p></o:p>
n frameMandatoryCaption:标记强制字段的文字<o:p></o:p>
n field:标签和输入框的布局<o:p></o:p>
n fieldLabel:包含一个标签的一段文字<o:p></o:p>
n fieldLabelMandatory:标记一个命令标签的一段文字<o:p></o:p>
n fieldInput:控制输入框<o:p></o:p>
n fieldInputMandatory:标记必须填写的文本框<o:p></o:p>
n button:执行命令的命令按钮<o:p></o:p>
n branding:对应每个书店的频道<o:p></o:p>
l 创建皮肤<o:p></o:p>
一旦我们UI的不同部分被决定,我们就可以使用Xkins创建两个皮肤。我们从在xkins-definition.xml文件中命名它们开始:<o:p></o:p>
<?xml version="1.0" encoding="UTF-8"?><o:p></o:p>
<xkins><o:p></o:p>
<skin name="base" url="/skins/forms/base" definition="/definition.xml"/><o:p></o:p>
<skin name="amazing" url="/skins/forms/amazing" definition="/definition.xml"/><o:p></o:p>
<skin name="bn" url="/skins/forms/bn" definition="/definition.xml"/><o:p></o:p>
</xkins><o:p></o:p>
现在,我们必须根据图4所示在Web应用根目录下创建一个目录结构:<o:p></o:p>
<o:p></o:p>
图4 皮肤目录<o:p></o:p>
在每个子目录,我们都要放置definition.xml文件来描述皮肤。我们来一起看看一些皮肤模板。如果需要查看所有的例子模板,可以从文件面末尾提供的链接中下载源代码。<o:p></o:p>
让我们来看看在包含Amazing的皮肤的definition.xml中皮肤的定义语法:<o:p></o:p>
<skin name="amazing" extends="base"><o:p></o:p>
<o:p></o:p>
</skin><o:p></o:p>
base是默认的皮肤,它和Xkins表单一起帮助我们给应用添加皮肤。Amazing的皮肤继承了它(Barnie&Nibble的也是)。我们现在开始为每个皮肤符覆盖base皮肤的模板,从覆盖field模板开始:<o:p></o:p>
<skin name="amazing" extends="base"> <template name="field" group="field"> <content><![CDATA[ $label $input ]]></content> </template> <template name="fieldLabel" group="field"> <content><![CDATA[ <td align=right style="font-family: verdana,arial,helvetica,sans-serif; font-size: x-small;"><b>$label:</b></td> ]]></content> </template> <template name="fieldLabelMandatory" group="field"> <content><![CDATA[ <td align=right style="font-family: verdana,arial,helvetica,sans-serif; font-size: x-small;"><b>$label:</b></td> ]]></content> </template> <template name="fieldInput" group="field"> <content><![CDATA[ <td colspan="$colspan" style="font-family: verdana,arial,helvetica,sans-serif; font-size: x-small;">$input (Optional)</td> ]]></content> </template> <template name="fieldInputMandatory" group="field"> <content><![CDATA[ <td colspan="$colspan"><strong>$input</strong></td> ]]></content> </template> </skin><o:p></o:p>
上面所有的模板都是Velocity模板。注意参数,象$colspan,是传递给模板的,可以被模板使用。这些参数在被标签库调用的XkinsProcessor传递。<o:p></o:p>
下面,我们开始从模仿的页面中把HTML剪切和粘贴到Xkins模板中。接着,我们使用相同的方法处理框架(frame)、按钮和频道。下面的代码显示了Barnie&Nibble的一块皮肤(只是field模版):<o:p></o:p>
<o:p></o:p>
<skin name="bn" extends="base"><o:p></o:p>
<path name="images" url="/images" /><o:p></o:p>
<element name="spacer" path="images" url="/cleardot.gif"/><o:p></o:p>
<o:p></o:p>
<!-- field templates --><o:p></o:p>
<template name="field" group="field"><o:p></o:p>
<content><![CDATA[<o:p></o:p>
<o:p></o:p>
<td width="100%"><o:p></o:p>
<table border=0 cellpadding=0 cellspacing=0 width="100%"><o:p></o:p>
<tr><o:p></o:p>
$label<o:p></o:p>
</tr><o:p></o:p>
<tr><o:p></o:p>
$input<o:p></o:p>
</tr><o:p></o:p>
</table><o:p></o:p>
]]></content><o:p></o:p>
</template><o:p></o:p>
<template name="fieldLabel" group="field"><o:p></o:p>
<content><![CDATA[<o:p></o:p>
<o:p></o:p>
<td WIDTH="25%"><font size="-1" <o:p></o:p>
face="arial, helvetica, sans-serif">$label</font></td><o:p></o:p>
]]></content><o:p></o:p>
</template><o:p></o:p>
<template name="fieldLabelMandatory" group="field"><o:p></o:p>
<content><![CDATA[<o:p></o:p>
<o:p></o:p>
<td WIDTH="25%"><font size="-1" face="arial, helvetica, sans-serif">$label</font></td><o:p></o:p>
]]></content><o:p></o:p>
</template><o:p></o:p>
<template name="fieldInput" group="field"><o:p></o:p>
<content><![CDATA[ <o:p></o:p>
<td colspan="$colspan" style="font-family: verdana,arial,helvetica,sans-serif; font-size: x-small;"><o:p></o:p>
$input <br><b>(Optional)<o:p></o:p>
</b></td><o:p></o:p>
]]></content><o:p></o:p>
</template><o:p></o:p>
<template name="fieldInputMandatory" group="field"><o:p></o:p>
<content><![CDATA[ <o:p></o:p>
<td WIDTH="25%">$input <img src="$res_mandatory" border="0"/></td><o:p></o:p>
]]></content><o:p></o:p>
<element name="mandatory" path="images" url="/mandatory.gif"/><o:p></o:p>
</template><o:p></o:p>
<template name="nestedField" group="field"><o:p></o:p>
<!--<o:p></o:p>
jsp:bodyContent<o:p></o:p>
--><o:p></o:p>
<content><![CDATA[ <o:p></o:p>
<td colspan="$res_fieldColspan" style="font-family: verdana,arial,helvetica,sans-serif; font-size: x-small;"><o:p></o:p>
$bodyContent<o:p></o:p>
</td><o:p></o:p>
]]></content><o:p></o:p>
</template> <o:p></o:p>
<!-- end field templates --><o:p></o:p>
<!-- The rest of the templates go here --><o:p></o:p>
</skin><o:p></o:p>
<o:p></o:p>
l 使用皮肤<o:p></o:p>
现在我们具有了一个base皮肤和两个需要的皮肤,我们可以使用这些皮肤来创建JSP页面。为了完成这个工作,我们使用Xkins表单标签,因为他们使用了在base皮肤中定义了的模板。你可以象Xkins表单一样使用Xkins创建自己的标签库,这样你就不再需要使用Xkins表单了。但是Xkins表单和Struts框架兼容的很好,我们这个应用中就使用它。<o:p></o:p>
我们需要两个页面:<o:p></o:p>
n index.jsp:执行数据登录<o:p></o:p>
n done.jsp:打印结果<o:p></o:p>
我们的例子只是一个演示,所以不必真实的处理提交的请求,只需要从index.jsp重定向到done.jsp即可。在实际的应用中,在这些页面间的这个过程必须被完成。<o:p></o:p>
注意在我们的例子应用中Xkins是如何和Struts集成的。Xkins标签库并不替代Struts标签库,他们只是修饰页面的。例如,你不能使用<table>这个HTML标签,而是<forms:frame key="frame.title" width="30%">来容纳表单和添加皮肤能力。如果你的应用使用Struts,而且你想使用Xkins,只需要将在你的页面中放置Xkins表单标签库来修饰。接着,把所有在JSP页面中使用到的HTML标签传递给Xkins的模板,让Xkins产生视觉外观。<o:p></o:p>
虽然在例子中没有用到 |
相关推荐
——————————————win10系统上基于qt5.12通过qss实现一键换肤以及Font Awesome字体在qt中的应用,欢迎大家下载使用!!!——————————————win10系统上基于qt5.12通过qss实现一键换肤以及Font...
在安卓(Android)平台上开发应用时,为用户提供个性化的换肤功能已经成为提升用户体验的重要手段之一。这个名为"安卓Android源码——换肤.zip"的压缩包文件可能包含了实现这一功能的相关源代码,让我们来深入探讨...
通过利用LookAndFeels和Graphics2D,开发者可以轻松地为应用程序创建独特的视觉样式,同时保持代码的可维护性和跨平台兼容性。而具体到压缩包文件中的"com",可能包含的是实现这一功能的相关类或资源文件,例如Look...
本项目"Web浏览器带换肤"是一个基于C#实现的浏览器应用,它具有用户界面皮肤更换的功能,使得用户可以根据个人喜好定制浏览器的外观。这个项目对于C#初学者或者对UI设计感兴趣的开发者来说是一个很好的学习资源。 ...
总的来说,"皮肤选择器73款换肤winform皮肤Skins随你挑选"提供了一个丰富的WinForm应用皮肤解决方案,它可以帮助开发者轻松地实现应用界面的多样化和个性化,提升软件的整体视觉效果和用户体验。对于那些希望打造...
在本文中,我们将深入探讨如何在基于Windows Presentation Foundation(WPF)的客户端应用程序(CS结构桌面程序)中实现换肤功能。WPF是.NET Framework的一部分,它提供了丰富的用户界面(UI)设计工具和功能,使得...
4. 应用皮肤:在页面或整个应用程序级别引用皮肤文件,这样指定的控件就会呈现出皮肤定义的外观。 主题(Theme)则是一组皮肤的集合,它可以包含多个控件的皮肤文件。通过应用一个主题,可以同时改变页面上所有关联...
【标题】:“后台管理界面web换肤及easyui实例” 在Web开发中,提供可定制的用户界面(UI)换肤功能已经成为提升用户体验的重要手段。EasyUI是一个基于jQuery的前端框架,它为开发者提供了丰富的组件和简洁的API,...
例如,你可以使用`IrisSkin.SkinEngine.Init`方法初始化皮肤引擎,并指定窗体的主控件,这样所有子控件都会自动应用皮肤。同时,通过`IrisSkin.SkinEngine.AddSkinFile`方法,你可以加载皮肤文件(通常位于`Skins`...
2. **换肤工具**:换肤工具是专门用来快速更换应用皮肤的程序。这些工具通常提供简便的接口,允许开发者或者用户选择不同的皮肤主题,一键切换,无需修改源代码。对于开发者来说,这可以极大地节省时间和精力,同时...
在安卓(Android)平台上,开发应用时,提供换肤功能是一项常见的需求,它能为用户提供个性化的体验。本文将深入探讨“安卓Android源码——精典源码之换肤”的核心概念和技术实现。 首先,我们要理解换肤的本质是...
你可以根据需要替换"Me",将其换成你要应用皮肤的具体控件或窗体。 除了基础的皮肤应用,SkinSharp还提供了许多高级功能。例如,你可以动态切换皮肤,或者在运行时改变皮肤,只需更改SkinManager对象的SkinFilePath...
6. **本地存储与记住设置**:为了提供更好的用户体验,可以使用浏览器的localStorage或cookie来存储用户的皮肤选择,以便他们在下次访问时自动应用上次选择的皮肤。 7. **响应式设计**:在设计皮肤时,还要考虑响应...
在实践中,开发者可以将这些皮肤文件解压,然后通过`ResourceDictionary`引用它们,使应用能够使用新的视觉样式。 另一份压缩文件"wpf皮肤主题.zip"很可能包含了更多的皮肤主题,同样提供源码和调试程序。源码部分...
4. 应用皮肤:一旦皮肤加载成功,可以通过`SkinManager.ApplySkin()`方法将皮肤应用到整个应用程序或指定控件。 5. 切换皮肤:根据需要,可以提供用户界面元素让用户选择不同的皮肤,通过调用`SkinManager....
2. **应用皮肤**: - 在应用程序启动时或者用户选择皮肤时,加载相应的皮肤资源。 - 使用`Application.Current.Resources.MergedDictionaries.Add()`方法将皮肤资源字典合并到全局资源中。 - 为了确保内置控件也...
Skin++是一个专门用于MFC应用的皮肤引擎,它为MFC应用程序提供了强大的换肤能力。Skin++设计的核心理念是通过XML文件来描述界面元素的外观和行为,使得开发者无需深入研究图形界面的底层实现,就能轻松实现软件的...
4. **动态加载**:为了实现换肤,程序需要支持在运行时动态加载和应用皮肤文件,无需重启应用。这要求程序有相应的接口或设置选项来触发皮肤切换。 5. **兼容性和性能**:换肤功能需要考虑兼容性,确保不同皮肤在...