Posted on 1 Comment

AS3的事件傳遞機制(Event、dispatchEvent及addEventListener)

當事件被發送出來之後。Event一般來説都會有一個Flow。 Flow分三個部分:

  1. Capture(捕獲階段)
  2. Targeting(目標階段)
  3. Bubbling(冒泡階段)

其關係圖如下:(來源為http://www.adobe.com/devnet/actionscript/articles/event_handling_as3.html)

efAzj

值得一提的是,在FLASH裡,只有和UI相關的物件,會有上圖所示的目標及補獲階段的事件流

一般像是Timer、Loader事件,是直接進入目標階段,並不會有上圖所示的事件流的流程。
在宣告Event時,也可以先指定事件是否要完整的跑完全部的流程。

宣告事件的語法及及參數意義如下:

var event:Event = new Event(type, bubbles, cancelable);

參數說明(官方文件)

  1. type:String是要發送的事件的識別名稱EX:Event.COMPLETE
  2. bubbles:Boolean預設值是false,這個值是用來設定是否要有冒泡階段,如果傳false,代表他不會跑完全部的流程,只會從Capture到target階段就停止
  3. cancelable:Boolean預設值是false,這個值是用來設定是否這個事件可以被event.preventDefault();取消,如果設定為true的話,代表此事件是可以被取消的(稍候在dispatchEvent會更詳述這部份)。
    常用的可以取消的事件有(cancelable為true):   FocusEvent.MOUSE_FOCUS_CHANGEFocusEvent.KEY_FOCUS_CHANGETextEvent.TEXT_INPUT

而發送事件則是用這一段程式碼:

var result:Boolean = box.dispatchEvent(event);

在發送事件時,要注意,假使今天我們是在STAGE裡面有一個box物件,那當我們用box.dispatchEvent(event);
即使事件是用box發送的,事件還是會從stage > root > box這樣跑。(請見上圖)
假如在建立Event時,bubbles設為true,那在上圖跑的流程為stage > root > box > root > stage
而若bubbles設為false,跑的流程則是stage > root > box

當我們用root.dispatchEvent(event);
bubbles設為true,上圖跑的流程為stage > root > stage
bubbles設為false,流程為stage > root

由此可知,事件流只會到目標(Target),就會停止往下傳
假如今天box裡面有一個物件button,若是用box.dispatchEvent(event)
button物件是不會接到事件流的。(因為到目標階段便會開始bubbles或停止)
並且假如今天root裡同時有box和box2兩個物件,
假使我們用box.dispatchEvent(event),則box2也不會接到事件。

至於第三個在建立Event的參數cancelable,不論值是true或false,都不會影響事件流的流程。
那他的作用是做什麼的呢?

我們可以發現,dispatchEvent有回傳一個布林值,cancelable就是在影響這個布林值的傳回參數。
今天我們假如要創建一個物件,但是要讓使用者有權力去阻止這個事件發生後的後續發展時,可以這樣寫

if(this.dispathEvent(event)){
     trace("success!");
     //在這寫後續發展
}

假使使用者在監聽的途中呼叫 event.preventDefault();,並且EVENT的cancelable為true時,dispatchEvent回傳的值就會是false,便不會執行trace("success!");那塊區塊。但假使EVENT的cancelable為false時,不論你在事件執行中有沒有呼叫event.preventDefault(),dispatchEvent回傳的值就會是true

一般我們會在傳遞事件的途中,去將事件攔截下來。增加監聽事件的程式碼如下

box.addEventListener(MouseEvent.MOUSE_DOWN,parent1Event);

官網關於addEventListener的說明如下

addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

傳入的參數意義如下:

  1. type(String):事件名稱
  2. listener(Function):要執行的Function
  3. useCapture(Boolean):這個和本篇要說的事件流有關,當今天傳入的值為true,則只能在補獲階段去抓取事件,在冒泡階段是聽不到的。如果將 useCapture 設置為 true,則偵聽器只在捕獲階段處理事件,而不在目標或冒泡階段處理事件。
    如果 useCapture 為 false,則偵聽器只在目標冒泡階段處理事件
    要在所有三個階段都偵聽事件,需註冊 addEventListener 兩次:一次將 useCapture 設置為 true,一次將 useCapture 設置為 false。當今天若useCapture為true時,並不會聽到target階段時的事件但若為false時,也可以聽到target階段時的事件

    假使今天我們用box.dispatchEvent(event);來發送事件,
    然後box的監聽事件的useCapture設為true。ex : box.addEventListener(MouseEvent.CLICK, rootClick, true);
    這樣rootClick事件並不會被呼叫到。

    若box的監聽事件的useCapture設為false 。ex : box.addEventListener(MouseEvent.CLICK, rootClick, false);
    這樣rootClick事件便被呼叫到。

  4. priority(int):若今天同時有很多個監聽器同時監聽同一事件,可用這個值來設定那一個監聽器應該被優先執行。數字愈高代表會愈快執行該事件偵聽程式。
  5. useWeakReference(Boolean):是否使用弱關連。若是用弱關連,當被監聽的物件所指到的變數被指向記憶體的其他地方,這個關係也會一併被取消(物件會被GC回收)。但如果傳進的值是false,當今天被監聽的物件的其他關連被指向別處時,該物件不會被GC回收,需要手動removeEventListener時,該物件才會被GC回收。

除了上述的幾個參數外,還有幾個函數可以中斷事件流的流程。
那就是stopPropagation()stopImmediatePropagation()

那這兩個函數有什麼差別呢?

下圖可以很清楚的解釋差異:
stopPropagation():會把同一階層的其他事件跑完才停止。
5MYe3

stopImmediatePropagation():立刻停止之後所有的事件流。
jleAX

假如今天box同時有兩個監聽函數如下

box.addEventListener(MouseEvent.MOUSE_DOWN,eventMouseDownHandler1,false,1);
box.addEventListener(MouseEvent.MOUSE_DOWN,eventMouseDownHandler2,false,2);

則由於priority值的關係,eventMouseDownHandler2會先被執行,eventMouseDownHandler1在之後才被呼叫
那若是在eventMouseDownHandler2裡面呼叫event.stopPropagation(),eventMouseDownHandler1還是會被執行,才將事件流中斷。
但是若在eventMouseDownHandler2裡面呼叫event.stopImmediatePropagation(),則eventMouseDownHandler1就不會被呼叫到

相關資源

  1. AS3.0的事件機制(詳細)
  2. AS3筆記-事件流(event flow)
  3. Event propagation
  4. Introduction to event handling in ActionScript 3.0
Posted on

Flex裡綁定(Bindable)相關函數及使用方式

在flex裡,最強大的標籤應該就是[Bindable]的綁定標籤了
因為某次的需求,我需要研究將Bindable綁定至函數
也順便研究了ChangeWatcher和BindingUtils的使用

【BindingUtils】
官方的說明在此:
http://help.adobe.com/zh_TW/FlashPlatform/reference/actionscript/3/mx/binding/utils/BindingUtils.html
這是Flex內綁定的工具,裡面有兩個屬性,一個是綁定到函數(bindSetter),另一個則是綁定到某物件的某屬性(bindProperty)

使用範例如下
1. 綁定到函數(bindSetter)










2. 綁定到某物件的某屬性(bindProperty)










【ChangeWatcher】
官方的說明在此:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/binding/utils/ChangeWatcher.html
因為此次我們要綁定的函數裡是有帶多個參數的,因此BindingUtils的bindSetter便無法使用
這時就需要使用BindingUtils所用的ChangeWatcher來自己做綁定的動作
ChangeWatcher的使用方式如下
var model:Model = new Model();
watcherInstance = ChangeWatcher.watch(model,[“totalItems”],itemsChanged);
根據官方文件watch的傳入的東西依序為”要綁定的物件”、”要綁定的屬性”、”要綁定的函數”

下面便是我根據這些所寫的小範例
MyBindingUtils.as
package {
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.system.Capabilities;
import flash.utils.getTimer;

import mx.binding.utils.ChangeWatcher;
import mx.controls.Alert;
import mx.resources.ResourceManager;

public class MyBindingUtils extends EventDispatcher {

private static var _objs:MyBindingUtils;

public static function getInstance():MyBindingUtils {
if (_objs == null) {
_objs = new MyBindingUtils();
}
return _objs;
}

public function changeLanguage(lang:String):void {
ResourceManager.getInstance().localeChain = [lang, “en_US”];
this.dispatchEvent(new Event(“ChangeLanguage”));
}

[Bindable(event=”ChangeLanguage”)]
public function getString(type:String, key:String, parameters:Array = null, locale:String = null):String {
return ResourceManager.getInstance().getString(type, key, parameters, locale);
}

public function bindString(target:Object, prop:String, type:String, key:String, parameters:Array = null):String {
var w:ChangeWatcher = ChangeWatcher.watch(this, [“getString”], null);
var result:String = getString.apply(null, [type, key, parameters]);
if (w != null) {
var invoke:Function = function(event:*):void
{
result = getString.apply(null, [type, key, parameters]);
target[prop] = result;
};
w.setHandler(invoke);
invoke(null);
}
return result;
}
}
}

完整範例檔案可按此下載

Posted on

AS3.0中製作直式書寫的方式

在as3.0中有 FTE可針對文字去測量其寬度、高度等
針對個別的文字去做處理
相關官網的說明可見此
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS6C0BB8ED-2805-467a-9C71-F9D757F33FB6.html

ElementFormat是定義文字的相關屬性(字型、大小、顏色等等)
然後再new一個TextElement設定文字格式和文字內容
再將其放到一個TextBlock裡面

TextBlock裡面則有許多相關的操作函數
可以對個別的文字做旋轉、定位等等
http://livedocs.adobe.com/flex/3_cn/langref/flash/text/engine/TextBlock.html
詳細的手冊說明在上面

裡面的lineRotation將角度設為九十度(TextRotation.ROTATE_90)時
文字就會呈現傳統的中文直式書寫方式呈現

下面的是將文字改為直式文字的範例程式

package {
import flash.display.Sprite;
import flash.text.engine.FontDescription;
import flash.text.engine.TextBlock;
import flash.text.engine.TextElement;
import flash.text.engine.TextLine;
import flash.text.engine.TextRotation;
import flash.text.engine.ElementFormat;

public class TextBlock_lineRotationExample extends Sprite {

public function TextBlock_lineRotationExample():void {
var s:String = “一向批判電影不會「口下留情」的大陸媒體,竟在李安導演《少年PI的奇幻漂流》內地上映後,於中國最大入口網站搜狐,罕見大讚道:『影片美輪美奐的視覺奇觀,身臨其境的3D效果。』”;

var fontDescription:FontDescription = new FontDescription(“MS Mincho”);
var format:ElementFormat = new ElementFormat();
format.fontSize = 15;
format.fontDescription = fontDescription;

var textElement:TextElement = new TextElement(s, format);
var textBlock:TextBlock = new TextBlock();
textBlock.content = textElement;
textBlock.lineRotation = TextRotation.ROTATE_90;

var linePosition:Number = this.stage.stageWidth – 120;
var previousLine:TextLine = null;

while (true) {
var textLine:TextLine = textBlock.createTextLine(
previousLine,
300);
if (textLine == null)
break;
textLine.y = 30;
textLine.x = linePosition;
linePosition -= 24;
addChild(textLine);
previousLine = textLine;
}
}
}
}

Posted on

Label消除最後的…

使用mx的label時常常最後莫名其妙的出現…然後要把滑鼠移過去才可以以tip方式顯示出完整內容
這時要使用truncateToFit=”false”去關閉他自動縮排的功能

<mx:Label truncateToFit=”false” id=”lblSawFlopTotal” text=”{status.average_loss}”/>

Posted on

flex組件控制其內容創建時間

FLEX內的contains容器都會有一個屬性 creationPolicy可以控制其內容創建的時間
一般預設值都是auto
也就是當這個物件第一次被顯示時創建
這樣會有較好的使用者體驗

不過當我們有時使用viewStack
可能當我們在第一頁時
就必須指定第二或第三頁的label內容資料
那我們就必須把 creationPolicy設為all

creationPolicy總共有四種可能值
1. <strong>all :</strong> 產生物件時便產生所有的內部元件(即使它還沒有被顯示)
2. <strong>auto:</strong> 被顯示在畫面上時才創建物件
3. <strong>none:</strong> 永不自動創建
當creationPolicy屬性的值為none時,應該明確地指定容器的長和寬。正常情況下,Flex會自動對容器進行比例縮放以使它能夠容納子實例,但因為creationPolicy屬性的值設為none,開始時沒有實例化容器內的子實例,要進行比例縮放是不可能的。如果你沒有明確地調整容器的大小,直到容器內的子實例被實例化後才會自動調整大小以容納子實例。要手動實例化組件,請使用createComponentsFromDescriptors()方法。
4. queued: 根據creationIndex的順序來產生內容物件

比較需要注意的是 若今天我們照下面這樣寫
希望能夠當顯示getItemListShowPlace時馬上就設定testItem這個label的文字是什麼
一樣會產生testItem是null無法指定其值的錯誤 因為當物件是單一視圖時,all和auto是一樣的


   
   
   
   
      
   

正確的使用方式應如下


   
   
   
   
      
   

Posted on

ResourceManager動態載入多國語系的實現

事前準備工作
1.[撰寫Ant編譯時所使用的XML檔]
依照原有的XML去設定自己的SDK的位置,並且寫入要載入的語言檔

<?xml version="1.0" encoding="utf-8"?>
    <project name="Example resource bundle builder" basedir="." default="main">
    <!--這邊應設定為自己電腦的flex sdk的位置-->
    <property name="FLEX_HOME" value="C:\Program Files\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0" />
    <property name="APP_ROOT" value="${basedir}"/>
    <!--這邊需要載入ant編譯as檔案所需的flexTasks.jar以及所有相關編譯所需的函式庫-->
    <taskdef resource="flexTasks.tasks" >
        <classpath> <pathelement path="${FLEX_HOME}/ant/lib/flexTasks.jar"/>
            <pathelement path="${FLEX_HOME}/lib/flexTasks.jar"/>
            <fileset dir="${FLEX_HOME}/lib">
                <include name="**/*.jar"/>
            </fileset>
        </classpath>
    </taskdef>
    <!--定義所有的語言-->
    <target name="main">
        <antcall target="en_US"></antcall>
        <antcall target="zh_TW"></antcall>
    </target>
    <target name="en_US">
        <mxmlc>
            <locale>en_US</locale>
            <source-path>locale/{locale}</source-path>
            <include-resource-bundles>test</include-resource-bundles>
            <output>src/Resources_en_US.swf</output>
        </mxmlc>
    </target>
    <target name="zh_TW">
        <mxmlc keep-generated-actionscript="true">
            <allow-source-path-overlap>true</allow-source-path-overlap>
            <locale>zh_TW</locale>
            <source-path>locale/{locale}</source-path>
            <!--載入相關的函式庫-->
            <compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
                <include name="libs" />
                <include name="locale/{locale}" />
            </compiler.library-path>
            <!--定義要載入的語言檔案(可以用很多檔案)-->
            <include-resource-bundles>test</include-resource-bundles>
            <!--<include-resource-bundles>other</include-resource-bundles>-->
            <output>src/Resources_zh_TW.swf</output>
        </mxmlc>
    </target>
</project>

2.[設定Ant環境]
(a)Help->Software Updates更新flash builder的Ant編輯程式
(b)Windows->Show View->Other->Ant->Ant把視窗叫出來
(c)按Ant編譯視窗最左邊的Add Buildfiles,選擇剛剛寫的xml
(d)RUN他

3.[設定要產出的flex專案檔的編譯locale參數]
如果是要中文+英文則為-locale en_US zh_TW,如果少了這個動作在變語言時會發生缺少核心語言CORE檔案的問題。

4. locale檔副檔名是.properties

====================================
1. flex版本的實現及範例下載
http://www.nbilyk.com/flex-localization-example

2. 為flash builder安裝ant
http://www.judahfrangipane.com/blog/2007/12/13/flex-builder-3-ant-support/

3. 官方關於ResourceManager的類別資料
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/resources/ResourceManager.html

4. 在flash裡實現多國語系
http://ticore.blogspot.com/2010/07/as3-project-multi-languages.html

5. 各種實現方式
http://blog.csdn.net/fireson/archive/2010/01/12/5181343.aspx

[學習經歷]
首先先至[flex版本的實現及範例下載]下載多國語系範例
然後到[為flash builder安裝ant]實際編譯ResourceManager的語言檔為swf
再依範例自行試看看如何實現

Posted on

在flex3的button內文字增加文字陰影

http://www.myflexhero.com/share/flex-hero-flex4/flex-hero-components/flex-hero-style/flex-hero-filters/962
上面的連結是教學我們如何在label上增加文字濾鏡
那我們要如何在按鈕上增加文字濾鏡呢?
主要就是要在按鈕生成後抓取裡面的文字元件然後增加濾鏡效果

btn.addEventListener(FlexEvent.CREATION_COMPLETE,addFilter);

抓取button的label的方式是下面這行

((e.target as Button).getChildAt(1) as TextField).filters = myFilters;

所以整個函數可能如下

import flash.filters.*;

//增加文字陰影
private function addFilter(e:Event):void{
var f:DropShadowFilter = new DropShadowFilter(3,30,0×000000,.8);
var myFilters:Array = new Array();
myFilters.push(f);
((e.target as Button).getChildAt(1) as TextField).filters = myFilters;
}

Posted on

Flex Module 多個module的Domain問題和最大化

最近在弄模組 總是遇到下面這篇文章所說的錯誤
實在搞了半天 看到這篇文章實在很開心
如有人遇到相類似的錯誤 可以參考看看喔
原文網址:http://wangwangliujun.spaces.live.com/blog/cns!550C6565FCCAE686!9407.entry?sa=735791548

需求背景 :
在同一個檔案裡載入多個模組,並且某些類別是跨模組的,會在不同的模組間被使用到,
例如 : DragManager、PopUpManager等等
當把物件從模組a拖到模組b時,會出現下面的錯誤
TypeError: Error #1034: 強制轉換類型失敗:無法將 mx.managers::PopUpManagerImpl@7155ac1 轉換為 mx.managers.IPopUpManager。

問題原因分析:
屬於ModuleLoader shared code problem .
當Module中使用managers時(如PopUpManager、DragManager、HistoryManager等)則可能出現這個問題(當application裡在loader之前沒有引入這些manager的引用時)。
manager的方法是靜態方法,整個應用程序中創建了一個該manager接口的singleton實例,但module僅在自己的 Application domain中使用該單例, 當多個module使用同一個單例manager且main application沒有使用時,就會出現這個空對像引用問題:第一個引入某manager的module不能將該manager接口的 singleton跟其他module共享,其他module調用該Manager的方法時,應用程序不會再創建該manager接口的實例,這個 module就無法引用到該manager接口的實例,就出現了空對像引用問題.

解決辦法如下:
1. 設domain

cursorManager.setBusyCursor();
currentModule = new ModuleLoader();
//設置當前的域為 application域
currentModule.applicationDomain = ApplicationDomain.currentDomain;
currentModule.addEventListener(ModuleEvent.READY,moduleSetup);
currentModule.url = s;
currentModule.loadModule();
PopUpManager.addPopUp(currentModule,CanMap, false);

2. 在主模組下載入該類別
在Application加入下面的程式碼:

import mx.managers.DragManager;

Posted on

Flex 獲得png透明截圖的問題和解決方法

代碼大概這樣:

// displaObject 為需要截圖對像
var pngEncoder:PngEncoder = new PngEncoder();
var bitMapData:BitmpaData = new BitmpaData(displaObject.widht,displaObject.height);
bitMapData.draw(displaObject);
var imageByteArray:ByteArray = pngEncoder.encode(bitMapData);

但是得到結果並不透明,於是懷疑encode方法沒有包含Alpha通道。改為第二種方法:

var bytes:ByteArray = bitmapData.getPixels(new Rectangle(0,0,bitmapData.width,bitmapData.height));
var imageByteArray2:ByteArray = pngEncoder.encodeByteArray(bytes,bitmapData.width,bitmapData.height,true);

結果仍然沒有透明度信息!
於是仔細讀了手冊每一項找到如下一段話:
transparent:Boolean (default = true) — 指定位圖圖像是否支持每個像素具有不同的透明度。默認值為 true(透明)。若要創建完全透明的位圖,請將 transparent 參數的值設置為 true,將 fillColor 參數的值設置為 0x00000000(或設置為 0)。將 transparent 屬性設置為 false 可以略微提升呈現性能。
也就是說,transparent = true 還不行,fillColor還必須設置為 0x000000!!

var bitMapData:BitmpaData = new BitmpaData(displaObject.widht,displaObject.height,true,0x000000);

其實這樣設置挺說不通的,但是以後碰到問題還是要多看看手冊了!
smaller by the complexes with cellulose also be very important for relaxation and properties called phytochemicals could be impossible to do that Lush sell thymol which studied the botanical free option but the breakdown of natural molecules in the method in the botanical free forms of lead A number of animal or find more uniform it is just due to achieve In the collagen peptides for relaxation and resorption of bone mass and other substances capable of inhibiting the strength and other forms of