Archive for the ‘Actionscript’ Category

actionscript获取google pagerank

星期日, 4月 19th, 2009

本来我是打算用这个代码让在线的swf文件提供动态查询pr值的功能,代码从php版本的移植过来,调试都很好,等生成swf的时候才想起来,flashplayer的安全限制决定了这个功能只能在本地沙盒运行,因为访问的是www.google.com的域,而google的在线存储之类用的是其他的二级域。不过写是写了,作为AIR程序使用倒是可以的。
本来我是打算用这个代码让在线的swf文件提供动态查询pr值的功能,代码从php版本的移植过来,调试都很好,等生成swf的时候才想起来,flashplayer的安全限制决定了这个功能只能在本地沙盒运行,因为访问的是www.google.com的域,而google的在线存储之类用的是其他的二级域。不过写是写了,作为AIR程序使用倒是可以的。

[snippet=14111]

调用时先实例化,然后设置pr值返回时候的callback方法,调用getPR方法即可。

Flex中AdvancedDataGrid的AdvancedDataGridColumn两种格式定义方法

星期六, 3月 7th, 2009

在用flex做一个股票版的演示,避免自己写太多的代码,就使用AdvancedDataGrid好了。

有些数据需要显示红色,有些数据需要显示绿色,当然了,这是股价。而有些数据不齐全,需要计算出来,比如有现价和昨收,而没有涨跌幅,这个需要使用现价和昨收计算出来。

1.根据数据显示红绿的方法:
在AdvancedDataGrid中指定一个styleFunction=”colStyle”
然后在actionscript段中实现这个colStyle:

private function colStyle(data:Object, col:AdvancedDataGridColumn):Object
{
var diff:Number = Number(data[col.dataField]) - Number(data["last"]);
//计算该列的数据与昨收的价差
if (diff < 0)
{
return {color:”green”}; //比昨收低,返回绿色
}
else
{
return {color:”red”};   //比昨收高,返回红色
}
}

当然,这仅是个简单的示例,还有不少细节需要完善的。

2.对于dataProvider里面没有的数据,比如涨跌额和涨跌幅,则使用AdvancedDataGridRendererProvider进行渲染

在AdvancedDataGrid的AdvancedDataGridColumn指定两列:

<mx:AdvancedDataGridColumn headerText=”涨跌” width=”64″ id=”change” />
<mx:AdvancedDataGridColumn headerText=”%”  width=”54″ id=”ratio” />

id分别是change和ratio.

然后在AdvancdeDataGrid中指令两个RenderProvider:

<mx:rendererProviders>
<mx:AdvancedDataGridRendererProvider column=”{ratio}” columnSpan=”1″

renderer=”RatioRender” />
<mx:AdvancedDataGridRendererProvider column=”{change}” columnSpan=”1″

renderer=”ChangeRenderer”/>
</mx:rendererProviders>

分别实现RatioRender和ChangeRenderer

ChangeRenderer.mxml:

<?xml version=”1.0″?>
<mx:Label xmlns:mx=”http://www.adobe.com/2006/mxml” textAlign=”center”>
<mx:Script>
<![CDATA[

override public function set data(value:Object):void
{
var diff:Number;
if (Math.abs(Number(value["now"])) < 0.001) diff = 0;
else diff = Number(value["now"]) - Number(value["last"]); //计算价差
if (Math.abs(diff) < 0.001)  //如果差距小于1/10分,就用黑色
{
setStyle(”color”, “black”);
}
else if (diff < 0)
{
setStyle(”color”, “green”);
}
else
{
setStyle(”color”, “red”);
}
text = diff.toFixed(2);          //设置显示内容,并限制小数点位数
setStyle(”textAlign”, “right”);  //右对齐
}

]]>
</mx:Script>

</mx:Label>

RatioRender.mxml也类似。

其余红绿的显示实际上也可以用2的方法来显示,只不过,针对不同的列,由于不能把列的信息传进这个Renderer里面,因此需要每个列单独写一个Renderer类,所以在内容可以使用dataProvider的列中,建议还是使用1的方法。

Flex中的CandleStickChart的自定义画法

星期二, 2月 10th, 2009

要用flex做股票行情软件了。

Flex让我不爽的地方在于,一些它做的控件其实做得并不完善,或者说是并没有考虑到实际的需求。

比如这个CandleStickChart里面的CandleStickSeries,可以设置fill和declineFill两种颜色,而那根蜡烛芯却不受这两个颜色控制,而是那个Stroke,是名符其实的一根线。当然还有boxStroke,是边框颜色的。

帮助文档里面的例子,干脆把这个Stroke和boxStroke都设成黑色,我怀疑这些开发人员都没看过真正的蜡烛图。

为了把那根最高-最低线颜色和fill/declineFill一致,不得不写as代码了(总的来说,我是抄SDK的):

找到这个CandlestickItemRenderer.as

仿照它的做法做一个别的ItemRenderer,比如CustomCandleStickRenderer

主要修改里面的updateDisplayList方法,由于懒得改CandleStickSeries的变量,这里我还是使用Stroke和boxStroke作为绿线和红线的变量:

原来的代码:

if (boxStroke)
boxStroke.apply(g);
else
g.lineStyle(0,0,0);
if (fill)
fill.begin(g,rc);
g.lineTo(rc.right, rc.top);
g.lineTo(rc.right, rc.bottom);
g.lineTo(rc.left, rc.bottom);
g.lineTo(rc.left, rc.top);
if (fill)
fill.end(g);
if (stroke)
{
stroke.apply(g);
g.moveTo(width / 2, 0);
g.lineTo(width / 2, (boxMin - max) * heightScaleFactor);
g.moveTo(width / 2, (boxMax - max) * heightScaleFactor);
g.lineTo(width / 2, height);
}

改成:

if (boxStroke && stroke) {
if (_chartItem.close > _chartItem.open)
boxStroke.apply(g);
else
stroke.apply(g);
}
else
g.lineStyle(0,0,0);
if (fill)
fill.begin(g,rc);
g.lineTo(rc.right, rc.top);
g.lineTo(rc.right, rc.bottom);
g.lineTo(rc.left, rc.bottom);
g.lineTo(rc.left, rc.top);
if (fill)
fill.end(g);
if (boxStroke && stroke)
{
g.moveTo(width / 2, 0);
g.lineTo(width / 2, (boxMin - max) * heightScaleFactor);
g.moveTo(width / 2, (boxMax - max) * heightScaleFactor);
g.lineTo(width / 2, height);
}

然后在原来的CandleStickSeries的属性里面加这么一行:

itemRenderer=”CustomCandleStickRenderer”

air能不能启动外部exe?

星期六, 1月 10th, 2009

在Windows环境中,AIR可以启动外部程序吗?

答案目前来说是不可以的。我想安全考虑是这样的,假如AIR可以自由调用windows的API和程序的话,那么AIR无疑能做很多事情,包括修改AIR的运行时本身,这样只要有一个AIR插入了危险代码,那么整个AIR运行时都不再安全,无疑AIR会成为病毒非常容易的入侵点。再加上AIR程序可以自动升级,令危险代码的部署就变得更容易了。

那么AIR不是还能访问本地文件吗?

AIR访问本地文件其实是有限制的:

http://help.adobe.com/zh_CN/AIR/1.1/devappsflex/WS5b3ccc516d4fbf351e63e3d118666ade46-7f05.html

文中说明了一些应用程序沙箱,对应的flash程序的访问权限是受沙箱的限制的。

沙箱 说明
应用程序 文件位于应用程序目录中,并且使用完全 AIR 权限运行。
远程 文件来自 Internet URL,并且通过基于域的沙箱规则运行,该规则与适用于 Flash Player 中的远程文件的规则类似。(每个网络域都具有单独的远程沙箱,例如 http://www.example.com 和 https://foo.example.org。)
受信任的本地 文件为本地文件,且用户已使用“设置管理器”或 Flash Player 信任配置文件将其指定为受信任。文件可以从本地数据源读取数据并且与 Internet 通信,但不具有完全 AIR 权限。
只能与远程内容交互 文件为使用网络名称发布的本地 SWF 文件,但尚未受到用户的显式信任。文件可以与 Internet 进行通信,但不能从本地数据源读取数据。此沙箱仅可用于 SWF 内容。
只能与本地文件系统内容交互 文件为未使用网络名称发布的本地脚本文件,且尚未受到用户的显式信任。文件包含尚未受到信任的 JavaScript 文件。文件可以从本地数据源读取数据,但无法与 Internet 进行通信。

AIR程序所能访问的文件必须位于应用程序目录下。

==============================================================

当然,题目的问题可以改一个思路。比如先启动一个监控作用的monitor.exe,然后这个monitor.exe调用air程序,并与其进行socket或文件形式的交互,再由monitor.exe去启动air需要的外部程序。

flashplayer升级和非80端口的security policy

星期日, 1月 4th, 2009

踏入了2009,开始要把XIFF的那一套代码翻出来修改了。

编译没问题,然而一运行,就连不上Openfire,报错误为:

Error #2044: Unhandled SecurityErrorEvent:. text=Error #2048: Security sandbox violation: http://localhost/webim/main.swf cannot load data from [ServerName]:5222.

很明显是安全限制。

于是去查了一下web根目录下的crossdomain.xml,没有问题啊,放松了要求,不行,domain/port都改成*还是不行。

还是google,找回到http://www.igniterealtime.org的社区,里面说法很多,有说改openfire的,有说到adobe上下载一个perl脚本监听843端口的。

看明白了,这个问题的起因是flashplayer升级了,对于各种网络应用,都到其端口下获取安全策略文件,因此,80端口下的并不能用于5222端口,而一个通用的安全策略文件端口是843,因此可以在843上提供安全策略文件。

当然,对于XIFF+Openfire的这种情况,直接在XIFF中增加一句:

Security.loadPolicyFile(”xmlsocket://”+SERVERNAME+”:5229″);就可以了,Openfire默认提供flash安全策略文件的端口在5229。

在客户端flash可以修改的情况下,这个方案是最方便的。

====================================================

Adobe在安全上也是煞费苦心,感觉flashplayer越来越成熟了。

flex中用树来显示搜索结果

星期三, 12月 24th, 2008

具体的要求是,我有一个大的树用来显示股票的名称和代码,然而股票实在是太多了,我又需要增加一个输入框,用户输入股票代码的时候,检索出匹配的项目,显示在树的上方。

mxml:

<mx:TextInput x=”5″ y=”10″ width=”160″ height=”25″ fontSize=”12″ id=”searchbox”
text=”输入:股票代码/股票名称”
click=”if (searchbox.text.length > 10) searchbox.text=”;”
focusOut=”if (searchbox.text.length == 0) searchbox.text=’输入:股票代码/股票名称’”
change=”searchstock();”    />

<mx:Tree x=”5″ y=”40″ width=”274″ height=”100%” id=”tree_1″
dataProvider=”{categoryData}” labelFunction=”treeLabel” iconFunction=”treeIcon1″
itemClick=”tree1_itemClick(event)” fontSize=”12″></mx:Tree>

ActionScript:

private function searchstock():void {
                var resultCount:Number = 10;
                var kw:String = searchbox.text;
                var dept:XMLList = category.sortmethod.(@code == "400");                
                //根据具体的xml格式获取树中显示搜索结果的节点。
                var i:Number;
                var j:Number;
                var c:Number;

                while (dept[0].item.length() > 0) {    //清空上次的搜索结果
                    delete dept[0].item[0];
                }
               
                if (kw.length < 2) return;

                for (i = 0, c = 0; i < alphaxml.klist.length(); i++) { //根据具体情况遍历股票列表
                    for (j = 0; j < alphaxml.klist[i].item.length(); j++) {
                        if (alphaxml.klist[i].item[j].@name.indexOf(kw) >= 0 && c < resultCount) {
                            dept[0].appendChild(alphaxml.klist[i].item[j]); //匹配的条目加入搜索结果
                            c++;
                        }
                        if (c >= resultCount) break;
                    }
                    if (c >= resultCount) break;
                }

                tree_1.expandChildrenOf(tree_1.firstVisibleItem, true); //展开搜索结果
            }

主要是:
1.清空树的某节点下的所有内容,因为在文档里面查不到,最后翻翻网上的例子,用一个简单的delete就行了。
2.展开一个节点,expandChildrenOf