<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_spoony</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/32813/rss</id><updated>2010-11-16T13:41:39Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/32813/rss"/><entry><id>http://www.cnblogs.com/spoony/archive/2010/11/08/flex4-skinning-part04-notecard-demo.html</id><title type="text">Flex4 Skinning 4: 留言板示例</title><summary type="text">上一篇随笔讲了skinnable Spark component和skin之间的交互，其实在这些components背后并没有太高深的理论，它们只是通过元数据的方式定义一些skin part和skin state, 并在相关的属性上进行关联。自然有的时候我们需要override一些管理skin part和skin state生命周期的关键方法。本篇随笔试着创建一个skinnable Spart component. </summary><published>2010-11-08T04:22:00Z</published><updated>2010-11-08T04:22:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/11/08/flex4-skinning-part04-notecard-demo.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/11/08/flex4-skinning-part04-notecard-demo.html"/><content type="html">&lt;p&gt;上一篇随笔讲了skinnable Spark component和skin之间的交互，其实在这些components背后并没有太高深的理论，它们只是通过元数据的方式定义一些skin part和skin state, 并在相关的属性上进行关联。自然有的时候我们需要override一些管理skin part和skin state生命周期的关键方法。本篇随笔试着创建一个skinnable Spart component. &lt;/p&gt;&#xD;
&lt;p&gt;来看一个简单的类似留言板的示例。首先看一下想要做成的效果，如图5所示。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2010/29259/2010110812153245.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;Figure 5. 可以在一个面板上粘贴留言条&lt;/p&gt;&#xD;
&lt;p&gt;仔细观察可以发现每一个留言条都是有一些简单的控件组合而成，单独存在的留言条如图6所示。&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2010/29259/2010110812163389.png" alt="" /&gt;&amp;nbsp;Figure 6. 一个单独的留言条由文本标签和圆形关闭按钮组合而成&lt;/p&gt;&#xD;
&lt;p&gt;下面我们想新建这个组件，新建一个AS3类，名为NoteCard, 并继承skinnableComponent父类。如下代码所示：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;package com.guyue.components&#xD;
{&#xD;
	import spark.components.supportClasses.SkinnableComponent;&#xD;
	&#xD;
	public class NoteCard extends SkinnableComponent&#xD;
	{&#xD;
		public function NoteCard()&#xD;
		{&#xD;
			super();&#xD;
		}&#xD;
         }&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;然后为这个类用SkinState元数据方式添加相应的skin state, 一般情况下有两个：normal和disabled. 代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;[SkinState("normal")]&#xD;
[SkinState("disabled")]&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;接下来用SkinPart元数据方式定义需要的skin part, 如前面分析，一个简单的留言条由文本标签和圆形按钮组成，因此这里对其进行分别定义为labelDisplay和closeButton, 类型分别为TextBase和Button. 并注意closeButton的required=false, 代表了labelDisplay必须在skin文件中有对应id的标签，而closeButton则是可选的。元数据声明位于skin part名称也就是NoteCard类属性的上方。代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;[SkinPart(required="true")]&#xD;
	public var labelDisplay:TextBase;&#xD;
	&#xD;
	[SkinPart(required="true")]&#xD;
	public var closeButton:Button;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;接下来需要为skin part定义相关的属性。比如labelDisplay的text属性。代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;private var _text:String;&#xD;
&#xD;
	public function get text():String&#xD;
	{&#xD;
		return _text;&#xD;
	}&#xD;
&#xD;
	public function set text(value:String):void&#xD;
	{&#xD;
		if(_text == value)&#xD;
			return;&#xD;
		&#xD;
		_text = value;&#xD;
		&#xD;
		if(labelDisplay)&#xD;
			labelDisplay.text = value;&#xD;
	}&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;由于skin可以在运行时加载或者卸载，因此我们在程序刚开始运行时并不能保证component的相关skin文件已经准备完毕。所以需要对相应skin part属性进行动态设置。Flex框架会将skin中声明的skin part与component中的相关属性结合起来，并通过skinning生命周期中相应的方法进行通知。&lt;/p&gt;&#xD;
&lt;p&gt;这里的NoteCard类用到的相关方法主要有getCurrentSkinState(), partAdded(), partRemoved()这三个。这三个方法都在SkinnableComponent中有定义，因此只需要在子类中进行覆写。&lt;/p&gt;&#xD;
&lt;p&gt;getCurrentSkinState()方法是返回要要加载skin的component的state名称。比如这里的NoteCard类有disabled, enabled, 实现代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;override protected function getCurrentSkinState():String&#xD;
{&#xD;
	if(!enabled)&#xD;
		return "disabled";&#xD;
	&#xD;
		return "normal";&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;partAdded()方法会在skin part添加的时候被调用，因此在这个方法中，我们可以添加这个skin part的相关处理逻辑，比如事件监听等。这里的NoteCard类实现代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;override protected function partAdded(partName:String, instance:Object):void&#xD;
{&#xD;
	super.partAdded(partName, instance);&#xD;
	&#xD;
	if(instance == labelDisplay)&#xD;
		labelDisplay.text = _text;&#xD;
	&#xD;
	if(instance == closeButton)&#xD;
		closeButton.addEventListener(MouseEvent.CLICK, closeButton_clickHandler);&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;partRemoved()方法会在skin part移除的时候被调用，因此在这个方法中，我们可以将添加在这个skin part的相关处理逻辑进行移除，比如事件监听等。这里的NoteCard类实现代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;override protected function partRemoved(partName:String, instance:Object):void&#xD;
{&#xD;
	super.partRemoved(partName, instance);&#xD;
	&#xD;
	if(instance == closeButton)&#xD;
		closeButton.removeEventListener(MouseEvent.CLICK, closeButton_clickHandler);&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;可以看出partAdded()方法与partRemoved()方法是相对应的，其中用到的closeButton_clickHandler事件主要是将先前添加的留言条进行移除，实现方法如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;protected function closeButton_clickHandler(event:MouseEvent):void&#xD;
{&#xD;
	event.stopPropagation();&#xD;
	&#xD;
	IVisualElementContainer(parent).removeElement(this);&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;以上只是建立了SkinnableComponent, 接下来需要为它定义相关的皮肤才能达到想要的效果。在skins包中新建一个MXML Skin文件NoteCardSkin, 定义其HostComponent元数据属性为刚刚建立的NoteCard类。代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&#xD;
&amp;lt;s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" &#xD;
		xmlns:s="library://ns.adobe.com/flex/spark" &#xD;
		xmlns:mx="library://ns.adobe.com/flex/mx"&amp;gt;&#xD;
	&amp;lt;!-- host component --&amp;gt;&#xD;
	&amp;lt;fx:Metadata&amp;gt;&#xD;
		[HostComponent("com.guyue.components.NoteCard")]&#xD;
	&amp;lt;/fx:Metadata&amp;gt;&#xD;
&amp;lt;/s:Skin&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;接下来定义与NoteCard类中对应的states, 代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;s:states&amp;gt;&#xD;
	&amp;lt;s:State name="normal"/&amp;gt;&#xD;
	&amp;lt;s:State name="disabled"/&amp;gt;&#xD;
&amp;lt;/s:states&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;接下来是界面的组成部分，包括一个矩形，一个矩形中的文本标签和一个圆形按钮。最后NoteCardSkin皮肤的代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&#xD;
&amp;lt;s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" &#xD;
		xmlns:s="library://ns.adobe.com/flex/spark" &#xD;
		xmlns:mx="library://ns.adobe.com/flex/mx"&amp;gt;&#xD;
	&amp;lt;!-- host component --&amp;gt;&#xD;
	&amp;lt;fx:Metadata&amp;gt;&#xD;
		[HostComponent("com.guyue.components.NoteCard")]&#xD;
	&amp;lt;/fx:Metadata&amp;gt;&#xD;
	&amp;lt;!-- states --&amp;gt;&#xD;
	&amp;lt;s:states&amp;gt;&#xD;
		&amp;lt;s:State name="normal"/&amp;gt;&#xD;
		&amp;lt;s:State name="disabled"/&amp;gt;&#xD;
	&amp;lt;/s:states&amp;gt;&#xD;
	&amp;lt;!--  --&amp;gt;&#xD;
	&amp;lt;s:Rect width="300" height="200"&amp;gt;&#xD;
		&amp;lt;s:stroke&amp;gt;&#xD;
			&amp;lt;s:SolidColorStroke color="0xAA8E5E" weight="4"/&amp;gt;&#xD;
		&amp;lt;/s:stroke&amp;gt;&#xD;
		&amp;lt;s:fill&amp;gt;&#xD;
			&amp;lt;s:LinearGradient&amp;gt;&#xD;
				&amp;lt;s:GradientEntry color="0x60c2fe"/&amp;gt;&#xD;
				&amp;lt;s:GradientEntry color="0x70b2ee"/&amp;gt;&#xD;
			&amp;lt;/s:LinearGradient&amp;gt;&#xD;
		&amp;lt;/s:fill&amp;gt;&#xD;
	&amp;lt;/s:Rect&amp;gt;&#xD;
	&amp;lt;s:Label id="labelDisplay" left="10" top="10" width="280" height="180" color="0xFFF3E9" lineBreak="toFit" fontSize="18" fontFamily="Chalkboard"/&amp;gt;&#xD;
	&amp;lt;s:Button id="closeButton" skinClass="com.guyue.skins.NoteCardCloseButtonSkin" top="5" right="5"/&amp;gt;&#xD;
&amp;lt;/s:Skin&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;注意观察一下Label和Button的id属性，可以发现与NoteCard类中的SkinPart是对应的，这样在将skin应用到component上时，Flex会自动匹配。&lt;/p&gt;&#xD;
&lt;p&gt;另外圆形按钮closeButton也使用了一个自定义皮肤，使用这个皮肤会将Flex4自带的默认皮肤覆盖，这里我们需要再建立这个新的皮肤文件NoteCardCloseButtonSkin, 具体方法与上大同小异，代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&#xD;
&amp;lt;s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" &#xD;
		xmlns:s="library://ns.adobe.com/flex/spark" &#xD;
		xmlns:mx="library://ns.adobe.com/flex/mx"&amp;gt;&#xD;
	&amp;lt;!-- host component --&amp;gt;&#xD;
	&amp;lt;fx:Metadata&amp;gt;&#xD;
		[HostComponent("spark.components.Button")]&#xD;
	&amp;lt;/fx:Metadata&amp;gt;&#xD;
	&#xD;
	&amp;lt;!-- states --&amp;gt;&#xD;
	&amp;lt;s:states&amp;gt;&#xD;
		&amp;lt;s:State name="disabled" /&amp;gt;&#xD;
		&amp;lt;s:State name="down" /&amp;gt;&#xD;
		&amp;lt;s:State name="over" /&amp;gt;&#xD;
		&amp;lt;s:State name="up" /&amp;gt;&#xD;
	&amp;lt;/s:states&amp;gt;&#xD;
	&#xD;
	&amp;lt;s:Ellipse width="16" height="16"&amp;gt;&#xD;
		&amp;lt;s:stroke&amp;gt;&#xD;
			&amp;lt;s:SolidColorStroke color="0x131313" weight="1" /&amp;gt;&#xD;
		&amp;lt;/s:stroke&amp;gt;&#xD;
		&amp;lt;s:fill&amp;gt;&#xD;
			&amp;lt;s:LinearGradient&amp;gt;&#xD;
				&amp;lt;s:GradientEntry color="0xAA8E5E" color.over="0x9A7E4E" color.down="0x7A5E2E" /&amp;gt;&#xD;
				&amp;lt;s:GradientEntry color="0xCCBBAA" color.over="0xBCAB9A" color.down="0x9C8B7A"/&amp;gt;&#xD;
			&amp;lt;/s:LinearGradient&amp;gt;&#xD;
		&amp;lt;/s:fill&amp;gt;&#xD;
	&amp;lt;/s:Ellipse&amp;gt;&#xD;
	&#xD;
	&amp;lt;s:Label text="X" horizontalCenter="0" verticalCenter="0" /&amp;gt;&#xD;
	&#xD;
&amp;lt;/s:Skin&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;以上就是一个简单skinnable Spark component实现的示例。Flex强大的skinning机制使得它的实现非常容易。我们可以随时定义新的皮肤来完全改变这个component的外观。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1871650.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/11/08/flex4-skinning-part04-notecard-demo.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/spoony/archive/2010/11/03/flex4-skinning-part02-skinning-contract.html</id><title type="text">Flex4 Skinning 2: 皮肤协议</title><summary type="text">上一篇随笔中笔者介绍了如何为按钮制作一个简单的自定义皮肤，接下来分析一下皮肤文件的组成部分，并对皮肤协议（skinning contract）中各个部分进行详细介绍。</summary><published>2010-11-03T15:34:00Z</published><updated>2010-11-03T15:34:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/11/03/flex4-skinning-part02-skinning-contract.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/11/03/flex4-skinning-part02-skinning-contract.html"/><content type="html">&lt;p style="text-align: left;"&gt;上一篇随笔中笔者介绍了如何为按钮制作一个简单的自定义皮肤，接下来分析一下皮肤文件的组成部分，并对皮肤协议（skinning contract）中各个部分进行详细介绍。&lt;/p&gt;&#xD;
&lt;p&gt;首先可以看到根标签为Skin, 接下来是HostComponent元数据，这个可以在我们新建文件的时候指定，可以参照上一篇随笔的图1。&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;fx:Metadata&amp;gt;&#xD;
　　[HostComponent("spark.components.Button")]&#xD;
&amp;lt;/fx:Metadata&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;接下来就是states。&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;!-- states --&amp;gt;&#xD;
&amp;lt;s:states&amp;gt;&#xD;
   &amp;lt;s:State name="disabled" /&amp;gt;&#xD;
   &amp;lt;s:State name="down" /&amp;gt;&#xD;
   &amp;lt;s:State name="over" /&amp;gt;&#xD;
   &amp;lt;s:State name="up" /&amp;gt;&#xD;
&amp;lt;/s:states&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;来查看一下按钮（spark.components.Button）组件的源代码，准确说应该是按钮（spark.components.Button）类的父类按钮基类（spark.components.supportClasses.ButtonBase）, 找到元数据中带有SkinState元数据的部分，可以看到该类具有四个skin state: up, over, down disabled, 这与在皮肤文件中定义的states部分相对应。代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;//--------------------------------------&#xD;
//  Skin states&#xD;
//--------------------------------------&#xD;
&#xD;
/**&#xD;
 *  Up State of the Button&#xD;
 *  &#xD;
 *  @langversion 3.0&#xD;
 *  @playerversion Flash 10&#xD;
 *  @playerversion AIR 1.5&#xD;
 *  @productversion Flex 4&#xD;
 */&#xD;
[SkinState("up")]&#xD;
&#xD;
/**&#xD;
 *  Over State of the Button&#xD;
 *  &#xD;
 *  @langversion 3.0&#xD;
 *  @playerversion Flash 10&#xD;
 *  @playerversion AIR 1.5&#xD;
 *  @productversion Flex 4&#xD;
 */&#xD;
[SkinState("over")]&#xD;
&#xD;
/**&#xD;
 *  Down State of the Button&#xD;
 *  &#xD;
 *  @langversion 3.0&#xD;
 *  @playerversion Flash 10&#xD;
 *  @playerversion AIR 1.5&#xD;
 *  @productversion Flex 4&#xD;
 */&#xD;
[SkinState("down")]&#xD;
&#xD;
/**&#xD;
 *  Disabled State of the Button&#xD;
 *  &#xD;
 *  @langversion 3.0&#xD;
 *  @playerversion Flash 10&#xD;
 *  @playerversion AIR 1.5&#xD;
 *  @productversion Flex 4&#xD;
 */&#xD;
[SkinState("disabled")]&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;States是Flex4中skinning contract的重要组成部分。皮肤（skin）文件和相对应的控件组件（component）相互交互用到的正是skinning contract. 如同Button有四个state一样，每个skinning component都有一系列相对应的state, 可以通过component当前所处的state来对外观进行不同的设置。&lt;/p&gt;&#xD;
&lt;p&gt;组件的includeIn和excludeFrom属性为不同state的外观定义提供了很大便利。通过这两个属性可以在某特定的state下设置该state需要的外观。另外值得注意的是也可以通过&amp;ldquo;属性名.state=属性值&amp;rdquo;来进行更进一步的设置。如：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;s:SolidColor color="0x77CC22" color.over="0x92D64E" color.down="0x67A41D" /&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;以上代码段表示当按钮处于over state的时候，颜色为"0x92D64E"，其它state时颜色为"0x77CC22"。&lt;/p&gt;&#xD;
&lt;p&gt;SkinState元数据为皮肤文件中定义哪些state做了直接说明，如果皮肤中没有定义相关的state, 而且这个state被设置为required=true, 那么编译就会报错。&lt;/p&gt;&#xD;
&lt;p&gt;子类会从父类中集成state, 比如前面提到的四个skin state: up, over, down, disabled的定义并不存在于spark.components.Button中，而是在ButtonBase中。不过我们可以通过Exclude元数据对其进行过滤。&lt;/p&gt;&#xD;
&lt;p&gt;在开发过程中，如果改变state, 需要用到component的getCurrentSkinState()和invalidateSkinState()方法。getCurrentSkinState()用来追踪component的各个属性，并确定skin应该处于的state. invalidateSkinState()方法会使改变前的state失效并且根据getCurrentSkinState()方法返回值来设置当前的state. &lt;/p&gt;&#xD;
&lt;p&gt;有时候skin需要引用相关component的内容。如果设置了HostComponent元数据，那么在skin里面就可以直接调用。在skin和component之间交互数据有两种方式。推式（push method）是指component把数据推入到skin中。相反的，拉式（pull method）是指skin向component索要属性值数据。关于这两种数据传输方式并没有固定的规定，但是一般情况下，如果component中定义SkinPart为required=true, 则采用推式（push method）。&lt;/p&gt;&#xD;
&lt;p&gt;接下来我们可以在spark.components.supportClass.ButtonBase类定义中可以找到标有SkinPart的成员变量labelDisplay, 代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;//--------------------------------------------------------------------------&#xD;
//&#xD;
//  Skin parts&#xD;
//&#xD;
//--------------------------------------------------------------------------&#xD;
&#xD;
[SkinPart(required="false")]&#xD;
&#xD;
/**&#xD;
 *  A skin part that defines the label of the button. &#xD;
 *  &#xD;
 *  @langversion 3.0&#xD;
 *  @playerversion Flash 10&#xD;
 *  @playerversion AIR 1.5&#xD;
 *  @productversion Flex 4&#xD;
 */&#xD;
public var labelDisplay:TextBase;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;Skin part也是skin contract的重要组成部分。任何复杂的component都是由简单的组合而成。比如前面提到的按钮，就是由文本和矩形组成。文本就是按钮的skin part. 它由component声明，可以是可选的。定义的方式是使用SkinPart元数据，可以把这个元数据标记在任何公共的属性上，而属性的名称就成了这个part的名称。比如在按钮当中，labelDisplay就是一个SkinPart, 它被定义为可选的，类型为TextBase. &lt;/p&gt;&#xD;
&lt;p&gt;在component中定义了skin part后，需要在skin文件中进行对应的实现，比如我们可以将上一篇随笔中定义的label的id属性设置为labelDisplay, 这样Flex就会通过id属性自动将这个label与Button的labelDisplay相匹配。&lt;/p&gt;&#xD;
&lt;p&gt;将皮肤文件的Label部分改成如下代码所示：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;!-- text --&amp;gt;&#xD;
&amp;lt;s:Label id="labelDisplay" text="{hostComponent.label}" color="0x131313" &#xD;
		 textAlign="center" verticalAlign="middle" &#xD;
		 horizontalCenter="0" verticalCenter="1" &#xD;
		 left="12" right="12" top="6" bottom="6" /&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;可以发现，此时skin文件要想引用对应的component中的数据只需要使用hostComponent属性就可以了，这是因为我们在最开始就已经对元数据HostComponent进行了设置。修改相应的主应用程序，代码如下所示：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&#xD;
&amp;lt;s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" &#xD;
			   xmlns:s="library://ns.adobe.com/flex/spark" &#xD;
			   xmlns:mx="library://ns.adobe.com/flex/mx" &#xD;
			   minWidth="955" minHeight="600"&amp;gt;&#xD;
&#xD;
	&amp;lt;fx:Declarations&amp;gt;&#xD;
		&amp;lt;!-- Place non-visual elements (e.g., services, value objects) here --&amp;gt;&#xD;
	&amp;lt;/fx:Declarations&amp;gt;&#xD;
	&#xD;
	&amp;lt;fx:Style&amp;gt;&#xD;
		@namespace s "library://ns.adobe.com/flex/spark";&#xD;
		@namespace mx "library://ns.adobe.com/flex/mx";&#xD;
		s|Button {&#xD;
			skinClass:ClassReference("com.guyue.skins.SimpleButtonSkin");&#xD;
		}&#xD;
	&amp;lt;/fx:Style&amp;gt;&#xD;
	&#xD;
	&amp;lt;s:layout&amp;gt;&#xD;
		&amp;lt;s:VerticalLayout /&amp;gt;&#xD;
	&amp;lt;/s:layout&amp;gt;&#xD;
	&#xD;
	&amp;lt;s:Button label="Simple Button" /&amp;gt;&#xD;
	&#xD;
	&amp;lt;s:Button label="I used to be a button without customerized skin. " /&amp;gt;&#xD;
	&#xD;
&amp;lt;/s:Application&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;再次运行程序，可以发现现在两个按钮公用同样的皮肤，而且skin的定义在主应用程序端是完全透明的，这样外观和逻辑就实现了分离。如图3. &lt;/p&gt;&#xD;
&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2010/29259/2010110408442676.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;Figure 3. 使用样式可以同时为多个按钮设置皮肤&lt;/p&gt;&#xD;
&lt;p&gt;上面提到的TextBase是确定的类型，而且在声明周期中只会存在唯一的实例，称为静态的。当加载静态SkinPart的皮肤时，SkinnableComponent基类负责将所有的静态part从skin加载到component中。加载完毕之后，component就可以直接使用这些实例了。当part加载的时候，partAdded()会被调用，当part移除的时候partRemoved()方法会被调用。因此我们可以在这两个方法中添加相关事件处理逻辑。&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;/**&#xD;
 *  @private&#xD;
 */&#xD;
override protected function partAdded(partName:String, instance:Object):void&#xD;
{&#xD;
    super.partAdded(partName, instance);&#xD;
    &#xD;
    if (instance == labelDisplay)&#xD;
    {&#xD;
        labelDisplay.addEventListener("isTruncatedChanged",&#xD;
                                      labelDisplay_isTruncatedChangedHandler);&#xD;
        &#xD;
        // Push down to the part only if the label was explicitly set&#xD;
        if (_content !== undefined)&#xD;
            labelDisplay.text = label;&#xD;
    }&#xD;
}&#xD;
&#xD;
/**&#xD;
 *  @private&#xD;
 */&#xD;
override protected function partRemoved(partName:String, instance:Object):void&#xD;
{&#xD;
    super.partRemoved(partName, instance);&#xD;
    &#xD;
    if (instance == labelDisplay)&#xD;
    {&#xD;
        labelDisplay.removeEventListener("isTruncatedChanged",&#xD;
                                         labelDisplay_isTruncatedChangedHandler);&#xD;
    }&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;以上便是Button类中相关的代码，可以看出我们能够动态的为component中skin part添加或减少相关事件监听器。&lt;/p&gt;&#xD;
&lt;p&gt;但是有些时候我们需要动态的使用多个SkinPart的实例，比如spark.components.supportClasses.SliderBase这个类的所有子类的dataTip属性。这种SkinPart称为动态的。具体的代码如下所示：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;//--------------------------------------------------------------------------&#xD;
//&#xD;
//  Skin parts&#xD;
//&#xD;
//--------------------------------------------------------------------------&#xD;
&#xD;
[SkinPart(required="false", type="mx.core.IDataRenderer")]&#xD;
    &#xD;
/**&#xD;
 *  A skin part that defines a dataTip that displays a formatted version of &#xD;
 *  the current value. The dataTip appears while the thumb is being dragged.&#xD;
 *  This is a dynamic skin part and must be of type IFactory.&#xD;
 *  &#xD;
 *  @langversion 3.0&#xD;
 *  @playerversion Flash 10&#xD;
 *  @playerversion AIR 1.5&#xD;
 *  @productversion Flex 4&#xD;
 */&#xD;
public var dataTip:IFactory;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;可以看出dataTip属性的类型为Ifactory, 这表示开发人员可以动态的在component中对其实例利用createDynamicPartInstance()方法初始化，利用removeDynamicPartInstance()方法来移除。相应的partAdded()和partRemoved()方法与静态SkinPart处理相似。在一个component可以有多个动态part实例，何时调用createDynamicPartInstance()完全由开发人员根据需要来决定。&lt;/p&gt;&#xD;
&lt;p&gt;卸载skin基本上是自动进行的。程序运行时skin发生变化的时候就会调用detachSkin()方法。所有skin part相关的partRemoved()方法也会自动调用。开发人员可以在这两个方法里添加相应的事件监听。&lt;/p&gt;&#xD;
&lt;p&gt;有些复杂的component 可能需要在skin创建后某个不确定的时间与skin part进行交互。Component需要知道partAdded()方法可能在skin初始化很久以后才会被调用。这样的skin part被称为延迟的（deferred part）。一个典型的例子就是TabNavigator, 当用户点击了某个Tab之后，component才会知道新的part然后调用partAdded()方法。&lt;/p&gt;&#xD;
&lt;p&gt;图4是Adobe官方给出的skin parts生命周期。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/29259/2010110408464337.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;Figure 4. &lt;/p&gt;&#xD;
&lt;p&gt;本篇随笔中提到的state, skin part, data构成了skin contract. 他们共同实现了component及其skin的定义和交互。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1868616.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/11/03/flex4-skinning-part02-skinning-contract.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/spoony/archive/2010/11/01/flex4-skinning-part01-simple-button-skin.html</id><title type="text">Flex4 Skinning 1: 自定义一个简单按钮的皮肤</title><summary type="text">Flex4使得改变应用程序的外观变得异常简单，这主要归功于新的皮肤框架（skinning architecture），通过它我们可以将组件中的可视化元素和逻辑完全分离。也正因为这个思想的引导，我们可以发现Flex4中的组件本身都不再包含外观信息的定义，而是把这些信息放在相关的皮肤（skin）文件中。</summary><published>2010-11-01T02:09:00Z</published><updated>2010-11-01T02:09:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/11/01/flex4-skinning-part01-simple-button-skin.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/11/01/flex4-skinning-part01-simple-button-skin.html"/><content type="html">&lt;p&gt;Flex4使得改变应用程序的外观变得异常简单，这主要归功于新的皮肤框架（skinning architecture），通过它我们可以将组件中的可视化元素和逻辑完全分离。也正因为这个思想的引导，我们可以发现Flex4中的组件本身都不再包含外观信息的定义，而是把这些信息放在相关的皮肤（skin）文件中。&lt;/p&gt;&#xD;
&lt;p&gt;通过这系列文章，笔者将展示一下Flex4中的皮肤框架（skinning architecture）。首先，我们为常用的按钮（Button）组件定义一个新的皮肤。&lt;/p&gt;&#xD;
&lt;p&gt;新建相关的项目和包，然后新建一个MXML Skin文件。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2010/29259/2010110110043417.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;Figure 1. 新建皮肤文件并将其Host component设置为apark.components.Button&lt;/p&gt;&#xD;
&lt;p&gt;代码如下。&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&#xD;
&amp;lt;s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" &#xD;
		xmlns:s="library://ns.adobe.com/flex/spark" &#xD;
		xmlns:mx="library://ns.adobe.com/flex/mx"&amp;gt;&#xD;
	&amp;lt;!-- host component --&amp;gt;&#xD;
	&amp;lt;fx:Metadata&amp;gt;&#xD;
		[HostComponent("spark.components.Button")]&#xD;
	&amp;lt;/fx:Metadata&amp;gt;&#xD;
	&#xD;
	&amp;lt;!-- states --&amp;gt;&#xD;
	&amp;lt;s:states&amp;gt;&#xD;
		&amp;lt;s:State name="disabled" /&amp;gt;&#xD;
		&amp;lt;s:State name="down" /&amp;gt;&#xD;
		&amp;lt;s:State name="over" /&amp;gt;&#xD;
		&amp;lt;s:State name="up" /&amp;gt;&#xD;
	&amp;lt;/s:states&amp;gt;&#xD;
	&#xD;
	&amp;lt;!-- dropshadow for the down state only --&amp;gt;&#xD;
	&amp;lt;s:Rect radiusX="4" radiusY="4" top="0" right="0" bottom="0" left="0" includeIn="down"&amp;gt;&#xD;
		&amp;lt;s:fill&amp;gt;&#xD;
			&amp;lt;s:SolidColor color="0" /&amp;gt;&#xD;
		&amp;lt;/s:fill&amp;gt;&#xD;
		&amp;lt;s:filters&amp;gt;&#xD;
			&amp;lt;s:DropShadowFilter knockout="true" blurX="5" blurY="5" alpha="0.32" distance="2" /&amp;gt; &#xD;
		&amp;lt;/s:filters&amp;gt;&#xD;
	&amp;lt;/s:Rect&amp;gt;&#xD;
	&#xD;
	&amp;lt;!-- border and fill --&amp;gt;&#xD;
	&amp;lt;s:Rect id="rect" radiusX="4" radiusY="4" top="0" right="0" bottom="0" left="0"&amp;gt;&#xD;
		&amp;lt;s:fill&amp;gt;&#xD;
			&amp;lt;s:SolidColor color="0x77CC22" color.over="0x92D64E" color.down="0x67A41D" /&amp;gt;&#xD;
		&amp;lt;/s:fill&amp;gt;&#xD;
		&amp;lt;s:stroke&amp;gt;&#xD;
			&amp;lt;s:SolidColorStroke color="0x131313" weight="2" /&amp;gt;&#xD;
		&amp;lt;/s:stroke&amp;gt;&#xD;
	&amp;lt;/s:Rect&amp;gt;&#xD;
	&#xD;
	&amp;lt;!-- highlight on top --&amp;gt;&#xD;
	&amp;lt;s:Rect radiusX="4" radiusY="4" top="2" right="2" left="2" height="50%"&amp;gt;&#xD;
		&amp;lt;s:fill&amp;gt;&#xD;
			&amp;lt;s:LinearGradient rotation="90"&amp;gt;&#xD;
				&amp;lt;s:GradientEntry color="0xFFFFFF" alpha=".5"/&amp;gt;&#xD;
				&amp;lt;s:GradientEntry color="0xFFFFFF" alpha=".1"/&amp;gt; &#xD;
			&amp;lt;/s:LinearGradient&amp;gt;&#xD;
		&amp;lt;/s:fill&amp;gt;&#xD;
	&amp;lt;/s:Rect&amp;gt; &#xD;
	&#xD;
	&amp;lt;!-- text --&amp;gt;&#xD;
	&amp;lt;s:Label text="Simple Button" color="0x131313" &#xD;
			 textAlign="center" verticalAlign="middle" &#xD;
			 horizontalCenter="0" verticalCenter="1" &#xD;
			 left="12" right="12" top="6" bottom="6" /&amp;gt;&#xD;
		&#xD;
	&amp;lt;!-- SkinParts&#xD;
	name=labelDisplay, type=spark.components.supportClasses.TextBase, required=false&#xD;
	--&amp;gt;&#xD;
&amp;lt;/s:Skin&amp;gt;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;在主应用程序文件中使用按钮并设置它的皮肤属性（skinClass）。&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&#xD;
&amp;lt;s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" &#xD;
			   xmlns:s="library://ns.adobe.com/flex/spark" &#xD;
			   xmlns:mx="library://ns.adobe.com/flex/mx" &#xD;
			   minWidth="955" minHeight="600"&amp;gt;&#xD;
&#xD;
	&amp;lt;fx:Declarations&amp;gt;&#xD;
		&amp;lt;!-- Place non-visual elements (e.g., services, value objects) here --&amp;gt;&#xD;
	&amp;lt;/fx:Declarations&amp;gt;&#xD;
	&#xD;
	&amp;lt;s:layout&amp;gt;&#xD;
		&amp;lt;s:VerticalLayout /&amp;gt;&#xD;
	&amp;lt;/s:layout&amp;gt;&#xD;
	&#xD;
	&amp;lt;s:Button skinClass="com.guyue.skins.SimpleButtonSkin" /&amp;gt;&#xD;
	&#xD;
	&amp;lt;s:Button label="I am a button without customerized skin. " /&amp;gt;&#xD;
	&#xD;
&amp;lt;/s:Application&amp;gt;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/29259/2010110110075958.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;Figure 2. &lt;/p&gt;&#xD;
&lt;p&gt;这样一个最简单的按钮自定义皮肤就制作完成。从图2可以看出应用了我们定义的皮肤的按钮与默认的按钮的区别。使用皮肤的方法是设置组件的skinClass属性。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1865970.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/11/01/flex4-skinning-part01-simple-button-skin.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/spoony/archive/2010/10/15/air-local-database-accessing.html</id><title type="text">Air应用程序访问本地数据库</title><summary type="text">Adobe AIR 包括一个 SQL 数据库引擎，该引擎使用开放源代码 SQLite 数据库系统，支持具有许多标准 SQL 功能的本地 SQL 数据库。运行时未指定在文件系统上存储数据库数据的方式或位置。每个数据库都完全存储在单个文件中。开发人员可指定在文件系统中存储数据库文件的位置，单个 AIR 应用程序可访问一个或多个单独的数据库（即单独的数据库文件）。</summary><published>2010-10-15T03:07:00Z</published><updated>2010-10-15T03:07:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/10/15/air-local-database-accessing.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/10/15/air-local-database-accessing.html"/><content type="html">&lt;p&gt;Adobe AIR 包括一个 SQL 数据库引擎，该引擎使用开放源代码 &lt;a href="http://www.sqlite.org/"&gt;SQLite&lt;/a&gt; 数据库系统，支持具有许多标准 SQL 功能的本地 SQL 数据库。运行时未指定在文件系统上存储数据库数据的方式或位置。每个数据库都完全存储在单个文件中。开发人员可指定在文件系统中存储数据库文件的位置，单个 AIR 应用程序可访问一个或多个单独的数据库（即单独的数据库文件）。&lt;/p&gt;&#xD;
&lt;p&gt;flash.data 包中包含用于与 Adobe AIR 本地 SQL 数据库一起使用时的类。Adobe AIR 中包含 SQL 数据库引擎，该引擎支持从 AIR 应用程序内部创建和使用本地数据库。下面笔者将通过一个简单的查询数据操作示例来演示下使用flash.data包中的类来操作SQLite数据库。&lt;/p&gt;&#xD;
&lt;p&gt;使用的数据库管理工具为&lt;a href="http://www.sqliteexpert.com/"&gt;SQLite Expert&lt;/a&gt;，访问的数据库为该工具自带的示例数据库dbdemos，数据表为animals，如图1所示。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2010/29259/2010101511015697.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 1 &lt;em&gt;&amp;ldquo;A powerful administration tool for your SQLite databases.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;&#xD;
&lt;p&gt;首先新建Flex项目，注意选择的&amp;rdquo;Application type&amp;rdquo;为&amp;rdquo;Desktop(runs in Adobe AIR)&amp;rdquo;。在主应用程序文件中代码如下所示：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&#xD;
&amp;lt;s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" &#xD;
					   xmlns:s="library://ns.adobe.com/flex/spark" &#xD;
					   xmlns:mx="library://ns.adobe.com/flex/mx" &#xD;
					   creationComplete="init()"&amp;gt;&#xD;
	&#xD;
	&amp;lt;fx:Script&amp;gt;&#xD;
		&amp;lt;![CDATA[&#xD;
			import flash.data.SQLConnection;&#xD;
			import flash.data.SQLStatement;&#xD;
			import flash.events.SQLErrorEvent;&#xD;
			import flash.events.SQLEvent;&#xD;
			import flash.filesystem.File;&#xD;
			&#xD;
			import mx.collections.ArrayCollection;&#xD;
			import mx.controls.Alert;&#xD;
			&#xD;
			import vo.Animal;&#xD;
			&#xD;
			private var sqlConnection:SQLConnection;&#xD;
			private var sqlStatement:SQLStatement;&#xD;
			&#xD;
			private var Animals:ArrayCollection = new ArrayCollection();&#xD;
			&#xD;
			private function init():void&#xD;
			{&#xD;
				sqlConnection = new SQLConnection();&#xD;
				sqlConnection.addEventListener(SQLEvent.OPEN, openHandler);&#xD;
				sqlConnection.addEventListener(SQLErrorEvent.ERROR, errorHandler);&#xD;
				&#xD;
				sqlStatement = new SQLStatement();&#xD;
				sqlStatement.sqlConnection = sqlConnection;&#xD;
				sqlStatement.text = "SELECT * FROM animals";&#xD;
				sqlStatement.itemClass = Animal;&#xD;
				&#xD;
				var dbFile:File = File.applicationDirectory.resolvePath("data/dbdemos.db3");&#xD;
				sqlConnection.open(dbFile);&#xD;
			}&#xD;
			&#xD;
			private function openHandler(event:SQLEvent):void&#xD;
			{&#xD;
				sqlStatement.addEventListener(SQLEvent.RESULT, resultHandler);&#xD;
				sqlStatement.execute();&#xD;
			}&#xD;
			&#xD;
			private function errorHandler(event:SQLErrorEvent):void&#xD;
			{&#xD;
				Alert.show(event.error.details);&#xD;
			}&#xD;
			&#xD;
			private function resultHandler(event:SQLEvent):void&#xD;
			{&#xD;
				var result:SQLResult = sqlStatement.getResult();&#xD;
				if(result != null)&#xD;
				{&#xD;
					for(var i:int = 0; i &amp;lt; result.data.length; i++)&#xD;
					{&#xD;
						Animals.addItem(result.data[i]);&#xD;
					}&#xD;
				}&#xD;
			}&#xD;
			&#xD;
		]]&amp;gt;&#xD;
	&amp;lt;/fx:Script&amp;gt;&#xD;
	&#xD;
	&amp;lt;fx:Declarations&amp;gt;&#xD;
		&amp;lt;!-- Place non-visual elements (e.g., services, value objects) here --&amp;gt;&#xD;
	&amp;lt;/fx:Declarations&amp;gt;&#xD;
	&#xD;
	&amp;lt;s:Panel title="Air App Accessing Local Database Demo"&amp;gt;&#xD;
			&#xD;
		&amp;lt;mx:DataGrid dataProvider="{Animals}"&amp;gt;&#xD;
			&amp;lt;mx:columns&amp;gt;&#xD;
				&amp;lt;mx:DataGridColumn headerText="Name" dataField="NAME"/&amp;gt;&#xD;
				&amp;lt;mx:DataGridColumn headerText="Size" dataField="SIZE"/&amp;gt;&#xD;
				&amp;lt;mx:DataGridColumn headerText="Weight" dataField="WEIGHT"/&amp;gt;&#xD;
				&amp;lt;mx:DataGridColumn headerText="Area" dataField="AREA"/&amp;gt;&#xD;
				&amp;lt;mx:DataGridColumn headerText="BMP" dataField="BMP"/&amp;gt;&#xD;
			&amp;lt;/mx:columns&amp;gt;&#xD;
		&amp;lt;/mx:DataGrid&amp;gt;&#xD;
		&#xD;
	&amp;lt;/s:Panel&amp;gt;&#xD;
	&#xD;
&amp;lt;/s:WindowedApplication&amp;gt;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;由于其中使用到Animal实体类，因此需要定义，代码如下所示：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;package vo&#xD;
{&#xD;
	[Bindable]&#xD;
	public class Animal&#xD;
	{&#xD;
		public var NAME:String;&#xD;
		public var SIZE:int;&#xD;
		public var WEIGHT:int;&#xD;
		public var AREA:String;&#xD;
		public var BMP:String&#xD;
		&#xD;
		public function Animal()&#xD;
		{&#xD;
		}&#xD;
	}&#xD;
}&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;运行程序，可以看到结果，如图2所示。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2010/29259/2010101511061065.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 2 程序运行结果&lt;/p&gt;&#xD;
&lt;p&gt;除了查询操作外，常用的其它操作也可以执行，感兴趣的话请自行查阅相关资料。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1851993.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/10/15/air-local-database-accessing.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/spoony/archive/2010/07/27/the-little-code-girl.html</id><title type="text">[通篇转载]调程序的小女孩</title><summary type="text">实验室里冷极了，没有窗户，不知道是白天还是黑夜。这是一周的最后一天&amp;mdash;&amp;mdash;周末。在这又冷又黑的晚上，一个蓬头散发的小女孩在工位上坐着。她从家里出来的时候还穿着一件外套，但是有什么用呢？那是一件很大的外套──那么大，不知是哪一年买的。她工作的时候的，就把它脱掉了，实验室的师弟嘲笑说，可以拿它当抹布。 　　小女孩只好一个人做实验，一双小脚冻得红一块青一块的。她的破显示器屏幕上有一大...</summary><published>2010-07-27T10:29:00Z</published><updated>2010-07-27T10:29:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/07/27/the-little-code-girl.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/07/27/the-little-code-girl.html"/><content type="html">&lt;p&gt;实验室里冷极了，没有窗户，不知道是白天还是黑夜。这是一周的最后一天&amp;mdash;&amp;mdash;周末。在这又冷又黑的晚上，一个蓬头散发的小女孩在工位上坐着。她从家里出来的时候还穿着一件外套，但是有什么用呢？那是一件很大的外套──那么大，不知是哪一年买的。她工作的时候的，就把它脱掉了，实验室的师弟嘲笑说，可以拿它当抹布。&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;小女孩只好一个人做实验，一双小脚冻得红一块青一块的。她的破显示器屏幕上有一大段程序，手里草稿纸上还有一大段。这一整天，程序还是没调过，谁也没帮过她。&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;可怜的小女孩！她又冷又饿，哆哆嗦嗦地调程序。显示器的光落在她的干枯的长头发上，那头发卷曲着披在肩上，看上去很久没梳，不过她没注意这些。每个桌上都堆满了论文，实验室飘着一股油墨的香味，因为这是论文deadline的时间&amp;mdash;&amp;mdash;她可忘不了这个。&lt;/p&gt;&#xD;
&lt;p&gt;她在一行代码上停了下来，蜷着趴在桌子上。她觉得更冷了。她不敢跟老板说，因为她程序没调过，没拿到一个数据，老板一定会骂她的。再说，换做别的题目跟这个一样难。她们头上只有paper，虽然网上可以下到一些现成的代码，还是仍然没法用。&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;她的头脑几乎绝望了。啊，哪怕一次小小的成功，对她也是有好处的！她敢把上万行的代码修改一遍。编译运行一下，来找找问题么？她终于按下回车键开始运行。哧！程序开始输出信息了！一行一行的log开始出来了！她把小手拢在显示器上。多么温暖多么明亮的字符啊，简直像一支小小的蜡烛。这是一道奇异的火光！小女孩觉得自己好像坐在一个19寸液晶大显示器前面，显示器还是全新锃亮的，颜色鲜艳，字迹清晰，上边显示着程序输出的正确结果，多么舒服啊！哎，这是怎么回事呢？她刚把头伸出去，想看的仔细一些，程序crash了，大显示器不见了。她坐在那儿，眼前的破显示器上一行刺眼的segment fault。 &lt;/p&gt;&#xD;
&lt;p&gt;她又编译了一遍运行。程序又开始输出信息了，给出log了。显示器的光落在桌子上，那儿忽然变得像打印出来的paper那样洁白工整，她可以一直看到paper上的字迹。IEEE的logo，会议名称和日期，Abstract和Instroduction。更妙的是这篇paper的一作， 赫然署着自己的名字！看上去那么诱惑，一直向这个穷苦的小女孩走来。这时候，程序又crash了，她面前只剩一张又硬又旧的桌子。&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;她又运行了一遍。这一回，她感觉自己坐在布置整齐的会议室里。条幅上写着&amp;ldquo;博士毕业答辩&amp;rdquo;，比她去年师姐毕业时用的条幅还要大，还要美。红色的条幅上贴着那几个白色的黑体字，投影仪屏幕上许多幅美丽的彩色画片，跟顶级会议里的presentation一个样，在向她眨眼睛。小女孩向画片伸出手去。这时候，程序又crash了。只见ppt上的图片越升越高，最后成了在天空中闪烁的星星。有一颗星星落下来了，在天空中划出了一道细长的红光。 &lt;/p&gt;&#xD;
&lt;p&gt;&amp;ldquo;有一个什么人快要死了。&amp;rdquo;小女孩说。唯一疼她的师姐毕业前的时候告诉过她：一颗星星落下来，就有一个灵魂要到图灵那儿去了。&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;她又编译了一遍。这一回，她把所有的数组size都设大了。师姐出现在亮光里，是那么温和，那么慈爱。 &lt;/p&gt;&#xD;
&lt;p&gt;&amp;ldquo;师姐！&amp;rdquo;小女孩叫起来，&amp;ldquo;啊！请把我带走吧！我知道，程序一crash，您就会不见的，像那漂亮的显示器，发表的paper，布置好的答辩会议室一个样，就会不见的！&amp;rdquo; &lt;/p&gt;&#xD;
&lt;p&gt;她赶紧按了回车键，要把师姐留住。一大堆输出信息发出强烈的光，把实验室照得跟白天一样明亮。师姐从来没有像现在这样高大，这样美丽。师姐把小女孩抱起来，搂在怀里。她们俩在光明和快乐中飞走了，越飞越高，飞到那没有代码，没有论文，也没有毕业的地方去了。 &lt;/p&gt;&#xD;
&lt;p&gt;第二天清晨，这个小女孩坐在工位上，两腮通红，嘴上带着微笑。她死了，在周末的实验室累死了。新一周的太阳升起来了，照在她小小的尸体上。小女孩坐在那儿，手还按着在不知用过多少年的键盘上。 &lt;/p&gt;&#xD;
&lt;p&gt;&amp;ldquo;她想自己把程序调一下&amp;hellip;&amp;hellip;&amp;rdquo;人们说。谁也不知道她曾经看到过多么美丽的东西，她曾经多么幸福，跟着她师姐一起走向新世界的幸福中去。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1786242.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/07/27/the-little-code-girl.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/spoony/archive/2010/03/03/coldfusion-reports-5.html</id><title type="text">Adobe ColdFusion Reports（5）</title><summary type="text">    作为应用程序的一个很大组成部分，报表其实很少以单独形式存在，因此我们需要将报表作为模板应用到程序中。</summary><published>2010-03-03T07:28:00Z</published><updated>2010-03-03T07:28:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/03/03/coldfusion-reports-5.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/03/03/coldfusion-reports-5.html"/><content type="html">&lt;p align="left"&gt;作为应用程序的一个很大组成部分，报表其实很少以单独形式存在，因此我们需要将报表作为模板应用到程序中。前面的几篇随笔简单介绍了报表的基本制作和样式控制等。其中的查询内容信息直接放在报表中。通过Query Builder生成的query可以通过Query Builder的Advanced模式进行查看。如图1.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201003/2010030315242532.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 1&lt;/p&gt;&#xD;
&lt;p align="left"&gt;下面笔者通过一个示例，更改报表中的查询数据来动态显示不同的结果。使用者可以通过不同的用户名登录信息，查看当前登录的艺术家的作品信息。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;首先新建一个简单的登录窗体，代码如下。&lt;/p&gt;&#xD;
&lt;pre &gt;&amp;lt;h3&amp;gt;Artist Login Form&amp;lt;/h3&amp;gt;&#xD;
&amp;lt;p&amp;gt;Please enter your last name and password.&amp;lt;/p&amp;gt;&#xD;
&amp;lt;cfform name="loginform" action="artSalesReport.cfm" method="post"&amp;gt;&#xD;
	&amp;lt;table&amp;gt;&#xD;
		&amp;lt;tr&amp;gt;&#xD;
			&amp;lt;td&amp;gt;Last Name: &amp;lt;/td&amp;gt;&#xD;
			&amp;lt;td&amp;gt;&#xD;
				&amp;lt;cfinput type="text" name="username" &#xD;
					required="true" message="A username is required. "&amp;gt;&#xD;
			&amp;lt;/td&amp;gt;&#xD;
		&amp;lt;/tr&amp;gt;&#xD;
		&amp;lt;tr&amp;gt;&#xD;
			&amp;lt;td&amp;gt;Password: &amp;lt;/td&amp;gt;&#xD;
			&amp;lt;td&amp;gt;&#xD;
				&amp;lt;cfinput type="password" name="password" &#xD;
					required="true" message="A password is required. "&amp;gt;&#xD;
			&amp;lt;/td&amp;gt;&#xD;
		&amp;lt;/tr&amp;gt;&#xD;
	&amp;lt;/table&amp;gt;&#xD;
	&amp;lt;br/&amp;gt;&#xD;
	&amp;lt;cfinput type="submit" name="submit" value="Submit"&amp;gt;&#xD;
&amp;lt;/cfform&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;p align="left"&gt;然后新建一个应用页面，注意这里主要新建了一个查询变量，并将这个变量赋给cfreport标签的query属性，而将原来的报表文件赋给template属性，查看格式为HTML, 代码如下。&lt;/p&gt;&#xD;
&lt;pre &gt;&amp;lt;cfquery name="artsales" datasource="cfartgallery"&amp;gt;&#xD;
	SELECT &#xD;
		*&#xD;
	FROM&#xD;
		APP.ART,&#xD;
		APP.ARTISTS&#xD;
	WHERE&#xD;
		APP.ART.ARTISTID = APP.ARTISTS.ARTISTID&#xD;
		AND&#xD;
		APP.ARTISTS.LASTNAME = &amp;lt;cfqueryparam value="#FORM.username#"&amp;gt;&#xD;
	ORDER BY&#xD;
		APP.ARTISTS.LASTNAME&#xD;
&amp;lt;/cfquery&amp;gt;&#xD;
&#xD;
&amp;lt;cfreport query="artsales" template="ArtSalesReport1.cfr" format="HTML"&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;p align="left"&gt;在浏览器中运行程序，效果如图2, 图3.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201003/2010030315254268.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 2&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201003/2010030315255531.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 3&lt;/p&gt;&#xD;
&lt;p align="left"&gt;这里值得注意的是新建的查询中必须全部包括报表中的字段，当然可以增加新的字段。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1677258.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/03/03/coldfusion-reports-5.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/spoony/archive/2010/03/03/coldfusion-reports-4.html</id><title type="text">Adobe ColdFusion Reports（4）</title><summary type="text">    在web开发中，最经常用到的控制页面样式的方法就是通过CSS(级联样式单Cascading Style Sheet). 它能对布局、字体、颜色、背景和其它文图效果实现更加精确的控制。</summary><published>2010-03-03T07:21:00Z</published><updated>2010-03-03T07:21:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/03/03/coldfusion-reports-4.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/03/03/coldfusion-reports-4.html"/><content type="html">&lt;p align="left"&gt;在web开发中，最经常用到的控制页面样式的方法就是通过CSS(级联样式单Cascading Style Sheet). 它能对布局、字体、颜色、背景和其它文图效果实现更加精确的控制。好处主要如下：&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;只通过修改一个文件就可以改变多个网页外观和格式。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;在所有浏览器和平台之间的兼容性。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;更少的编码、更少的页数和更快的下载速度。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;在ColdFusion Report中，我们可以同样用CSS对报表的外观加以控制。用报表向导创建的报表将自动创建和应用下面的CSS元素：&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;ReportTitle&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;CompanyName&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;PageTitle&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;ReportDate&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;SubTitle&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;DetailData(default style)&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;DetailLabel&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;PageFooter&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;RectangleStyle&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;LineStyle&lt;/p&gt;&#xD;
&lt;p align="left"&gt;在ColdFusion Report Builder的Window -&amp;gt; Report Styles打开Report Styles&amp;nbsp;面板，可以看到各个样式元素属性对应的属性值。单击Export Report Styles, 可以将当前的CSS导出文件。打开导出的文件，如下：&lt;/p&gt;&#xD;
&lt;pre &gt;ReportTitle&#xD;
{&#xD;
		color:#91C9E4;&#xD;
		font-size:24pt;&#xD;
}&#xD;
CompanyName&#xD;
{&#xD;
		color:White;&#xD;
		font-weight:bold;&#xD;
}&#xD;
PageTitle&#xD;
{&#xD;
		color:#333333;&#xD;
		font-size:14pt;&#xD;
		font-weight:bold;&#xD;
}&#xD;
ReportDate&#xD;
{&#xD;
		color:#333333&#xD;
}&#xD;
SubTitle&#xD;
{&#xD;
		color:#0760B0;&#xD;
		font-size:12pt;&#xD;
		font-weight:bold;&#xD;
}&#xD;
DetailLabel&#xD;
{&#xD;
		color:White;&#xD;
		background-color:#0661B0;&#xD;
		font-weight:bold;&#xD;
}&#xD;
DetailData&#xD;
{&#xD;
		default-style:true;&#xD;
		color:#333333;&#xD;
		line-size:thin;&#xD;
}&#xD;
PageFooter&#xD;
{&#xD;
		color:#2F2F2F;&#xD;
		font-size:8pt;&#xD;
}&#xD;
RectangleStyle&#xD;
{&#xD;
		background-color:#0661B0&#xD;
}&#xD;
LineStyle&#xD;
{&#xD;
		color:#CCCCCC;&#xD;
		background-color:#CCCCCC;&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;p align="left"&gt;可以对其进行修改，比如将ReportTitle的color属性改为Red. &lt;/p&gt;&#xD;
&lt;pre &gt;PageTitle&#xD;
{&#xD;
		color:Red;&#xD;
		font-size:14pt;&#xD;
		font-weight:bold;&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;p align="left"&gt;然后单击Report Styles面板上的Import Report Styles按钮，将刚才修改后的CSS文件导入报表中，F12预览报表，可以发现报表的表头颜色变成了红色。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;对于报表纸张信息的控制，可以通过Report -&amp;gt; Report Properties实现。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1677249.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/03/03/coldfusion-reports-4.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/spoony/archive/2010/03/01/coldfusion-reports-3.html</id><title type="text">Adobe ColdFusion Reports（3）</title><summary type="text">    前面的随笔中我们提到过图表是很好的展示数据的工具，它能使显示更加直观。现在我们在报表中添加图表，以便于更加直观的展现数据信息。</summary><published>2010-03-01T01:24:00Z</published><updated>2010-03-01T01:24:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/03/01/coldfusion-reports-3.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/03/01/coldfusion-reports-3.html"/><content type="html">&lt;p align="left"&gt;现在我们在报表中添加图表，以便于更加直观的展现数据信息。前面我们新建了一个Calculated Field表示每个组中已售出的作品价格之和，下面为了对比&amp;ldquo;已售出&amp;rdquo;和&amp;ldquo;未售出&amp;rdquo;价格之和，我们再添加一个Calculated Field, Unsold. 如图1.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201003/2010030109195060.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 1&lt;/p&gt;&#xD;
&lt;p align="left"&gt;单击OK, 然后在LASTNAMEFooter添加一个图表控件，在Chart Type中选择Pie, 在Chart Sub-Type中选择3D. 如图2.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201003/2010030109201569.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 2&lt;/p&gt;&#xD;
&lt;p align="left"&gt;单击Next, 进入Chart Series, 单击Add, 在Series Label中输入Total Sales, 选择相应设置，添加Series Value Sold--#calc.Sold#.&amp;nbsp; 如图3.&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201003/2010030109204289.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 3&lt;/p&gt;&#xD;
&lt;p align="left"&gt;然后再添加Series Value Unsold--#calc.Unsold#, 单击OK回到Chart Series窗体。单击OK. 单击Next进入到Chart Formatting, 在Title&amp;amp;Series选项卡中，将Chart Title, X Axis Title, Y Axis Title分别设置为&amp;rdquo; Total Sales for #query.LASTNAME#&amp;rdquo;&amp;rdquo;Sold&amp;rdquo;&amp;rdquo;Unsold&amp;rdquo;, 如图4.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201003/2010030109211045.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 4&lt;/p&gt;&#xD;
&lt;p align="left"&gt;在Font选项卡中，分别将Font Name和Font Size设置为&amp;rdquo;Arial&amp;rdquo;&amp;rdquo;9&amp;rdquo;, 如图5.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201003/2010030109220868.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 5&lt;/p&gt;&#xD;
&lt;p align="left"&gt;保存报表，F12预览，效果如图6. 这样就为每个组添加了饼图图表信息。&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201003/2010030109223713.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 6&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1675386.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/03/01/coldfusion-reports-3.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/spoony/archive/2010/02/26/coldfusion-reports-2.html</id><title type="text">Adobe ColdFusion Reports（2）</title><summary type="text">    上一篇随笔只是用报表向导生成了一个最简单的报表，数据都是从数据库中直接获取，我们知道，数据库中存储数据可能比实际显示要简洁，因此显示的数据格式等还需要进一步完善。</summary><published>2010-02-26T12:54:00Z</published><updated>2010-02-26T12:54:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/02/26/coldfusion-reports-2.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/02/26/coldfusion-reports-2.html"/><content type="html">&lt;p align="left"&gt;上一篇随笔只是用报表向导生成了一个最简单的报表，数据都是从数据库中直接获取，我们知道，数据库中存储数据可能比实际显示要简洁，因此显示的数据格式等还需要进一步完善。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;默认情况下，用报表向导生成的报表列标题使用的是查询的列名，我们可以通过更改Column Header对其进行修改。双击Column Header部分的值便可进行修改。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;LASTNAME -&amp;gt; Artist Name&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;ARTNAME -&amp;gt; Title&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;DESCRIPTION -&amp;gt; Description&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;PRICE -&amp;gt; Price&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;middot;ISSOLD -&amp;gt; Sold?&lt;/p&gt;&#xD;
&lt;p align="left"&gt;ISSOLD字段存储的是&amp;rdquo;0/1&amp;rdquo;表示是否。我们需要将其转化为&amp;rdquo;Yes/No&amp;rdquo;，这样更加直观，毕竟用户可不想知道&amp;rdquo;0/1&amp;rdquo;分别表示什么意思。双击Detail中的query.ISSOLD单元格，调出Expression Builder. 找到Function -&amp;gt; Display and Formatting -&amp;gt; YesNoFormat, 双击，结果如图1. 单击OK. 设定完毕。&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022620510525.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 1&lt;/p&gt;&#xD;
&lt;p align="left"&gt;下面用同样的方法将PRICE字段格式化为带美元货币符号的数值。只需将原来的query.PIRCE改成DollarFormat(query.PRICE). &lt;/p&gt;&#xD;
&lt;p align="left"&gt;然后将组中的query.LASTNAME改为query.FIRSTNAME &amp;amp;&amp;rdquo; &amp;ldquo;&amp;amp;query.LASTNAME, 这样就可以显示艺术家的全名了。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;下面我们进行分页处理，使每个艺术家的作品进行分页显示。操作很简单，只需要使用Report -&amp;gt; Group Management, 如图2.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022620521255.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 2&lt;/p&gt;&#xD;
&lt;p align="left"&gt;前面提到过&amp;ldquo;组&amp;rdquo;的很大一个作用就是可以对该组进行摘要描述，比如我们在这里可以对每个艺术家的作品售出的价格进行汇总。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;打开Fields and Parameters面板（可以通过菜单栏的Window -&amp;gt; Fields and Parameters打开）。并添加一个Calculated Field. 如图3.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022620524434.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 3&lt;/p&gt;&#xD;
&lt;p align="left"&gt;在LASTNAME组的Footer添加一个新的字段，在弹出的Add Field对话框中选择calc.Sold, 别忘了对其进行美元货币符号格式化。此处注意是在LASTNAME组的Footer, 不要搞错位置。在刚才添加的字段前面添加一个标签&amp;rdquo;Total Sales&amp;rdquo;. &lt;/p&gt;&#xD;
&lt;p align="left"&gt;最后我们将报表头的&amp;rdquo;Company Name&amp;rdquo;替换为一个logo图片。删掉原来的文本框，加入一个Image控件，图片路径选择" C:\ColdFusion9\wwwroot\cfdocs\getting_started\photos\somewhere.jpg". &lt;/p&gt;&#xD;
&lt;p align="left"&gt;此时F12预览报表，效果如图4.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022620531497.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 4&lt;/p&gt;&#xD;
&lt;p align="left"&gt;可以看到按照艺术家分组，每组一页，并且相应的汇总信息也正确的显示出来。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1674544.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/02/26/coldfusion-reports-2.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/spoony/archive/2010/02/26/coldfusion-reports-1.html</id><title type="text">Adobe ColdFusion Reports（1）</title><summary type="text">    在应用程序开发过程中，报表设计开发是一项很繁琐的工作。首先要保证信息的详尽和直观。由于报表很多需要打印出来，所以也要对其大小规格进行详细设计。虽然所有浏览器都提供了打印功能，但是单单一个HTML格式的网页并不适合作为打印输出。</summary><published>2010-02-26T08:19:00Z</published><updated>2010-02-26T08:19:00Z</updated><author><name>spoony</name><uri>http://www.cnblogs.com/spoony/</uri></author><link rel="alternate" href="http://www.cnblogs.com/spoony/archive/2010/02/26/coldfusion-reports-1.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/spoony/archive/2010/02/26/coldfusion-reports-1.html"/><content type="html">&lt;p&gt;在应用程序开发过程中，报表设计开发是一项很繁琐的工作。首先要保证信息的详尽和直观。由于报表很多需要打印出来，所以也要对其大小规格进行详细设计。虽然所有浏览器都提供了打印功能，但是单单一个HTML格式的网页并不适合作为打印输出。在ColdFusion中，对于页面的&amp;ldquo;可打印的输出&amp;rdquo;需要保证有以下元素：&lt;/p&gt;&#xD;
&lt;p&gt;&amp;middot;页码&lt;/p&gt;&#xD;
&lt;p&gt;&amp;middot;页眉和页脚&lt;/p&gt;&#xD;
&lt;p&gt;&amp;middot;分页&lt;/p&gt;&#xD;
&lt;p&gt;&amp;middot;查看时的超链接&lt;/p&gt;&#xD;
&lt;p&gt;ColdFusion提供了两个标签用于&amp;ldquo;可打印的输出&amp;rdquo;：&lt;/p&gt;&#xD;
&lt;p&gt;&amp;middot;cfdocument&lt;/p&gt;&#xD;
&lt;p&gt;&amp;middot;cfreport&lt;/p&gt;&#xD;
&lt;p&gt;本文主要介绍使用Report Builder创建报表文件，并利用cfreport标签对其进行应用。Report Builder是ColdFusion中创建报表定义的有力工具，它包含了服务器端运行时和GUI。Report Builder只能运行在Windows操作系统上，可以用它来创建&amp;ldquo;带状报表&amp;rdquo;。&amp;ldquo;带状(banded)&amp;rdquo;指的是每个报表都有多个水平区域组成，每个区域就是一个&amp;ldquo;带(band)&amp;rdquo;。比如，报表头，页眉，页脚，中间的明细数据区域等等。这种理解方式相对比较直观，设计报表时我们可以讲&amp;ldquo;在某某带添加某某数据信息&amp;rdquo;，但是如果已经对报表设计有了基本的了解，没有必要如此，仅仅是说&amp;ldquo;添加页眉页脚信息&amp;rdquo;就可以了。&lt;/p&gt;&#xD;
&lt;p&gt;用Report Builder创建的报表格式为CFR。CFR文件包含了字段，格式，SQL语句，CFML等信息。我们可以通过前面提到的cfreport标签对CFR文件进行调用。此时应注意的有一点，虽然Report Builder这个报表工具只能用于Windows操作系统，但是已经用它创建好的CFR可以用于所有平台。&lt;/p&gt;&#xD;
&lt;p&gt;首先来熟悉一下Report Builder的基本环境。安装完毕，并且配置好RDS服务器后，启动程序，如图1.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022616084625.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 1&lt;/p&gt;&#xD;
&lt;p&gt;可以很直观的看出Report Builder提供了&amp;ldquo;工具箱&amp;rdquo;&amp;ldquo;对齐面板&amp;rdquo;&amp;ldquo;报表带&amp;rdquo;&amp;ldquo;属性面板&amp;rdquo;&amp;ldquo;字段和参数面板&amp;rdquo;&amp;ldquo;报表样式面板&amp;rdquo;。这些都是我们在使用其他的开发工具时很熟悉的。&lt;/p&gt;&#xD;
&lt;p&gt;下面通过向导来创建一个简单的报表示例。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;首先启动ColdFusion Report Builder, 进入到ColdFusion Report Builder Gallery, 如图2.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022616103628.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-align: center;"&gt;图 2&lt;/p&gt;&#xD;
&lt;p align="left"&gt;选择创建新报表向导，点击OK. 然后开始定义查询字段。如图3.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022616111850.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 3&lt;/p&gt;&#xD;
&lt;p align="left"&gt;单击Query Builder, 可以发现Query Builder是Report Buider的一个很强大的构建查询工具。如图4.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022616120297.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 4&lt;/p&gt;&#xD;
&lt;p align="left"&gt;双击RDS中cfartgallery数据源的ART和ARTISTS表并双击两个表中的ARTISTS.FIRSTNAME, ARTISTS.LASTNAME, ART.ARTNAME, ART.DESCRIPTION, ART.ISSOLD字段。如图5. 可以看出两表自动创建了关联，相应的SQL语句也已经自动生成。&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022616131493.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 5&lt;/p&gt;&#xD;
&lt;p align="left"&gt;单击Test Query来测试一下，如图6.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022616144788.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 6&lt;/p&gt;&#xD;
&lt;p align="left"&gt;关闭查询测试窗体，单击Query Builder的Save按钮。可以看到刚才选择的字段都被默认放到了Printed Fields中。这些都是在运行报表时会显示的内容。双击FIRSTNAME将其放入Non-printed Fields中。如图7.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022616160032.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 7&lt;/p&gt;&#xD;
&lt;p align="left"&gt;单击Next进入到Define Report Grouping. 如图8.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022616162988.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 8&lt;/p&gt;&#xD;
&lt;p align="left"&gt;&amp;ldquo;组&amp;rdquo;在报表中是个很重要的概念。组可以使报表显示的信息更加清晰。每个组都可以单独定义标题和相对于此组的概要等，比如一些汇总信息。ColdFusion并不自动对数据进行分组，因此我们需要通过SQL语句中的ORDER BY进行处理。实际上，当在选择分组字段时候，Report Builder会自动更新原来生成的SQL语句，加上ORDER BY部分。&lt;/p&gt;&#xD;
&lt;p align="left"&gt;在这里双击Available Fields中的LASTNAME字段，添加到Group By Fields中。单击Next. 进入到Report Layout. 选择自己喜欢的然后单击Next. &lt;/p&gt;&#xD;
&lt;p align="left"&gt;处理完Layout, Style, Theme, 并给报表取合适的名称，单击Finish. 这样一个简单报表就完成了。保存并F12预览一下，如图9.&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;&lt;img src="http://pic002.cnblogs.com/img/spoony/201002/2010022616165314.png" /&gt;&lt;/p&gt;&#xD;
&lt;p align="left" style="text-align: center;"&gt;图 9&lt;/p&gt;&#xD;
&lt;p align="left"&gt;可以看到报表按照各个艺术家的名字进行分组显示。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/spoony/aggbug/1674356.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/spoony/archive/2010/02/26/coldfusion-reports-1.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
