Posts tagged ‘flex’

Django系列谈(一)

Python是一种很优雅的语言。优雅这个字,在我理解是,用最少的话表达最多的意思,说白了就是开发效率。我觉得作为程序员应该会一种优雅的语言。在紧急或者懒惰的情况下,可以最快最高效的帮助完成一些任务。作为一个flashflex的coder,最头疼的莫过于,需要后台,至少说,需要一个测试用的后台。Python是搭建简易后台最有效率的技术之一。

这个“之一”一定要讲,不然容易造成论战。不错,除了python,有人还喜欢ruby,或者php。他们code的效率同样很高。争来争去是没有意义的,我感觉,与其耍嘴皮子,搞些有意义没意义的辩论,还不如关注你手上可以用的资源。如果你认定了Python,那么马上学习吧,拿起来就用吧,我们只是要测试用后台不是么,黑猫白猫,能抓老鼠就是好猫。邓爷爷的话一定要相信。

如果你惦记着纯用Python搭服务器,那你一定够傻了。要知道python可以做很多事情,能力很强的劣势就是,比较“底层”(当然跟C比较的话,编程效率高)。为什么不用framework呢。flash的开发效率同样比较低,所以才有flex冒出来。framework就是用来降低工作量的,就像很多所谓的牛人在给他们的产品做广告时说的那样,我们尽可能的让开发者关注业务,而不是实现。说的多好。

Django是很好很强大的web framework。它的好处是:

  • 自带一个测试服务器。可以免去IIS和apache。不需要安装额外的服务器软件。
  • 绝少的配置选项。
  • 自带一个简易的管理系统。可以管理数据库的增删改。
  • 依靠python解释执行的好处,做修改可避免服务器重启
  • 快速实现MVC

上面是虚的,实的嘛,下回分解。

UIComponent之currentStateChange事件

在使用State的时候,我总是会选择enterState和exitState事件来处理state切换问题(enterState总是在state切换完毕再抛出,这点很便利),可是最近发现一问题,enterState和exitState实际是抛出FlexEvent对象,此对象不包含上一个state和请求的state的信息,也就是说,你也不会知道你是从哪个state切换过来的,对于某些特别的request来说不是很爽。

于是我查了下UIComponent的源码,发现UIComponent带有两个很好用的事件

  • currentStateChange
  • currentStateChanging

在UIComponent的commitCurrentState方法(private)里,还能找到这两个事件,以及enterState,exitState抛出的顺序:

  1. currentStateChanging
  2. exitState
  3. enterState
  4. currentStateChange

从这里不难发现flex framework对于state的处理机制,首当其冲便是currentState property,它存储着state信息。切换的时候,首先抛出currentStateChanging事件,说明切换开始,然后执行“移除”当前state,抛出exitState(至此state被移除),然后切换到新的state,完成后抛出enterState,接着抛出currentStateChange事件,currentState修改完毕。

并且我们可以注意到,currentStateChange抛出的是StateChangeEvent事件对象,此对象带有oldState和newState property,恰好弥补了enterState和exitState的不足。

分页组件

以前写的一段Flex分页组件,可以复用。样式如下,左右各有一组”<<”和”<”,分别表示跳到第一页和前一页(相对应的,跳到最后一页和后一页),屏幕上页面数字只会显示7个,功能很基本。

fy

fy2

fy3

这套组件主要是用到了LinkButton和Repeater。

<!-- page -->
<mx:HBox id="paginationbox" width="100%" height="24"
		 verticalAlign="middle" horizontalGap="0"
		 visible="false">
	<mx:Label text="PAGES: "/>
	<mx:Spacer width="3"/>
	<mx:LinkButton label="&lt;&lt;"
				   styleName="pageLinkBtn"
				   enabled="{_curr_page_index!=0}"
				   click="showImagesInList()"/>
	<mx:LinkButton label="&lt;"
				   styleName="pageLinkBtn"
				   enabled="{_curr_page_index &gt; 0}"
				   click="showImagesInList(_curr_page_index-1)"/>
	<mx:Repeater id="prepeater"
				 dataProvider="{_pages}"
				 count="7"
				 startingIndex="{(_curr_page_index-3 &lt; 0)?0:(_curr_page_index-3)}">
		<mx:LinkButton label="{(prepeater.currentIndex+1).toString()}"
					   enabled="{int(prepeater.currentIndex) != _curr_page_index}"
					   styleName="pageLinkBtn"
					   click="showImagesInList(event.currentTarget.repeaterIndex)"/>
	</mx:Repeater>
	<mx:LinkButton label="&gt;"
				   enabled="{_curr_page_index &lt; _pages.length-1}"
				   click="showImagesInList(_curr_page_index+1)"
				   styleName="pageLinkBtn"/>
	<mx:LinkButton label="&gt;&gt;"
				   enabled="{_curr_page_index != _pages.length-1}"
				   click="showImagesInList(_pages.length-1)"
				   styleName="pageLinkBtn"/>
</mx:HBox>

style比较简单

.pageLinkBtn
{
	paddingLeft:0;
	paddingRight:0;
	paddingTop:0;
	paddingBottom:0;
}

升级Flex sdk 带来的错误一例

错误信息:

VerifyError: Error #1053: Illegal override of FlexModuleFactory in mx.core. FlexModuleFactory. at global$init()

看样子就是跟Module相关的,包括从CSS编译过来的SWF。这个问题是由Flex sdk升级导致,需要使用新的sdk重新编译Module和SWF,这样载入进来才“合拍”。完了不要忘了清空缓存再测试

Degrafa的Bezier源码浅析(一)

先解释下Bezier曲线:

http://en.wikipedia.org/wiki/Bézier_curve

Degrafa是一套很强大的图形算法类库,并且开源,对Bezier曲线的绘制提供了很好的支持。说起Bezier曲线,其实就是Photoshop和flash里常用的钢笔工具啦,主要就是用来绘画路径或者绘画不规则图形。前者的应用领域非常广泛,比如使图形沿着路径运动,或者按路径不规则排列图形(具体一例就是扭曲的美术字布局)。这些都会用到Bezier曲线。

Degrafa提供的tutorial不是很完备,很多时候为了扩展应用不得不看源码。我这里只就Bezier相关的处理过程分析一下。

Degrafa下面的类非常之多,跟Bezier相关的主要有:

  • com.degrafa.geometry.splines.BezierSpline
  • com.degrafa.geometry.CubicBezier

两者都继承自com.degrafa.geometry.Geometry。很多图形库都有着类似的继承体系,Geometry作为一个基础的图形类,下面还有很多经过定义的不同种类的图形。

CubicBezier看字面意思,是一个三次贝塞尔曲线,事实上确实如此,它有四个点(start,end,2 control points)控制,其实也就是wiki上的那个图形

而BezierSpline跟真正的钢笔工具非常像,它由一系列点和control points来控制一整条曲线。这里最好看它的注释:

The BezierSpline can be used for drawing of a smooth curve through
multiple points, with some shape control over the curve via a tension
parameter. It may also be used for general path animation with tension
control, optional closed-path control, and velocity control
(arc-length parameterization).

乍看一下,它好像就是若干个CubicBezier的组合,其实关系不是很近。BezierSpline内部确实用到了CubicBezier对象(源码的第一行private var _bezier:Array),它是用来管理三次bezier曲线段的(BezierSpline包括很多的段)。

在使用BezierSpline曲线之前,需要提供一系列的点(钢笔工具的点类似)。使用到的property包括:

  • points
  • data

两者实质相同形式不同而已。

绘画曲线都使用draw方法,这个方法是由Geometry定义,并由它的子类重写的(典型的继承体系)。BezierSpline和CubicBezier都有类似的draw定义方式:

/**
* Begins the draw phase for geometry objects. All geometry objects
* override this to do their specific rendering.
*
* @param graphics The current context to draw to.
* @param rc A Rectangle object used for fill bounds.
**/
override public function draw(graphics:Graphics,rc:Rectangle):void{	

	//re init if required
 	if (invalidated) preDraw(); 

	//init the layout in this case done after predraw.
	if (_layoutConstraint) calculateLayout();

	super.draw(graphics, (rc)? rc:bounds);

}

preDraw在这个体系里非常重要,是用来在绘画之前计算各个点的位置,就像我们使用graphic那样定义好MoveTo和lineTo,所不同的这里会用到很多算法。与draw一样,preDraw在Geometry里定义在子类里重写,每个子类都有不同的方法。比如BezierSpline:

/**
* @inheritDoc
**/
   override public function preDraw():void{
   	if( invalidated ){

        	if(!points.length){return;}

        	_assignControlPoints();

        	//add a move to for the first item.
        	commandStack.length=0;

	//add a MoveTo at the start of the commandStack rendering chain
	commandStack.addMoveTo(points[0].x,points[0].y);

	var cubic:CubicBezier;

        //todo not sure were this extra one is coming from yet.
        //re:: - 1 on the count
        for( var i:uint=0; i<_bezier.length-1; ++i ){

        	cubic = _bezier[i];

        	commandStack.addCubicBezierTo(cubic.x0,cubic.y0,cubic.cx,
       	cubic.cy,cubic.cx1,cubic.cy1,cubic.x1,cubic.y1,1);

  	}

     		invalidated = false;
}
	    }

挖到这里,基本上快看到bezier算法在Degrafa里怎么实现的了,关键就是这个commandStack,字面意思:命令退栈,命令集合。

localhost下模拟慢网速

Flash IDE 可以为调试的swf模拟网速来测试进度条。如果是Flex builder呢,似乎是没有的,不过千万别在这个问题上钻牛角尖,因为这实际上是本地服务器的职责,而不是flex builder该干的工作(flex builder编译完成并启动页面后就结束任务了)。

在这种情况下要为flex模拟慢网速的话,就要使用proxy工具了,我这里推荐ServiceCapture,当然很多http检测工具都带有模拟网速的功能,我选serviceCapture除了它能检测http,还能读出trace和AMF协议,简直是Flash专用工具。

首先你需要安装serviceCapture for firefox 插件,让它“干预”firefox上的调试。

sc_1

sc_2

然后所有在firefox里发生的http和AMF连接都会被记录下来,serviceCapture “中转”了firefox的请求,这样就能人为的拖慢网速。

sc_3

Flex builder 配合 FlashDevelop开发模式

每次谈到Flex builder和FlashDevelop这两个工具总不免比较一番,其实两者各有优点为什么不互补一下呢。事实上我在实践过程中,觉得有些情况下两个配合着用非常不错。FlashDevelop有轻便的优势,代码提示很好,而Flex builder支持Flex framework,支持可视化开发,搭建UI快捷编码量少。

什么时候配合着用比较好呢。那就是开发AS类库,类库用FlashDevelop开发,轻便快捷,而测试使用Flex builder,快速构建UI来显示效果,提供参考。

通过观察FlashDevelop project的文件夹可以发现,基本上FlashDevelop和Flex builder的布局是差不多的,source code放在src里,编译文件放bin,类库放lib等等。于是就有两种配合方式可供参考:

  • 叠在一块儿。先用FlashDevelop建一个project,然后Flex builder也建在同一个位置。
  • 分开建project。Flex builder使用external source path来链接类库代码。

显然第二种方式更好,可以有效的将测试代码和类库代码分开。

Flex源码学习之mx.utils.*

我承认这个标题有点标题党的味道。其实我的意思是想说,flex framework里有些code并不是依赖于framework的,怎么说呢,它们是纯算法,是数据处理,而并没有用到其它的flex framework class已经一些,比如metadata特性(有也可以改掉)。比如下面要提到的mx.utils.ColorUtil,还有StringUtil。于是我们就可以把它们提炼出来,用在普通AS3/Flash project当中,而不需要依赖,导入flex framework。

flex sdk已经开源了,进入sdk folder查找ColorUtil。来看看它处理brightness的算法

/**
 *  Performs a scaled brightness adjustment of an RGB color.
 *
 *  @param rgb Original RGB color.
 *
 *  @param brite The percentage to brighten or darken the original color.
 *  If positive, the original color is brightened toward white
 *  by this percentage. If negative, it is darkened toward black
 *  by this percentage.
 *  The range for this parameter is -100 to 100;
 *  -100 produces black while 100 produces white.
 *  If this parameter is 0, the RGB color returned
 *  is the same as the original color.
 *
 *  @return New RGB color.
 */
public static function adjustBrightness(rgb:uint, brite:Number):uint
{
	var r:Number;
	var g:Number;
	var b:Number;
 
	if (brite == 0)
		return rgb;
 
	if (brite < 0)
	{
		brite = (100 + brite) / 100;
		r = ((rgb >> 16) & 0xFF) * brite;
		g = ((rgb >> 8) & 0xFF) * brite;
		b = (rgb & 0xFF) * brite;
	}
	else // bright > 0
	{
		brite /= 100;
		r = ((rgb >> 16) & 0xFF);
		g = ((rgb >> 8) & 0xFF);
		b = (rgb & 0xFF);
 
		r += ((0xFF - r) * brite);
		g += ((0xFF - g) * brite);
		b += ((0xFF - b) * brite);
 
		r = Math.min(r, 255);
		g = Math.min(g, 255);
		b = Math.min(b, 255);
	}
 
	return (r << 16) | (g << 8) | b;
}

是不是很优雅。Adobe的精英工程师创造出来的,效率及简介性肯定可以保证,况且开源了,为啥不好好利用呢。flex code里有很多好货可以发掘。

另一款别致的AutoCompleteComboBox

原文见这里,名字叫FilterComboBox。继承自ComboBase,可以根据输入的文字来自动匹配dataprovider,并显示在下拉列表,相当实用的Flex组件

sample点击这里。右键可以查看源码

FlexDbg试用 — debug plugin of FlashDevelop

FlashDevelop这个IDE本身是不带断点调试的,但是可以通过插件的方式来支持。FlexDbg就是这么一款好用的插件(下载见这里)。使用步骤如下:

  1. 下载(废话)最新版zip包
  2. 打开FlashDevelop的安装文件夹,进入Plugin文件夹,将下载的zip包解压到这里(几个dll文件)
  3. 打开或重启FlashDevelop,应该发现menu上多了debug选项
  4. debug的方式几乎和别的IDE没啥不同,不过注意了,不再是点“Test Movie” 这个蓝色小箭头来启动debug,而是menu->debug->Start,要用菜单栏的。

我的感觉,FlexDbg的调试跟visual studio感觉一样。开发AS没有断点调试功能怎么行,快试试看吧。