<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    咖啡伴侶

    呆在上海
    posts - 163, comments - 156, trackbacks - 0, articles - 2

    深入Flex4 -- 了解Element和Child的異同 轉

    Posted on 2011-10-14 11:05 oathleo 閱讀(830) 評論(0)  編輯  收藏 所屬分類: Flex

    當我了解到Flex4那些對我諸多裨益的新特性后, 我便決定轉而使用它。剛開始的時候,我試圖利用在Flex前作中的認識和既有經驗來快速進入狀態。但很快我便發現有時即使面對一些顯而易見的問題我也不得 不求助于API文檔或者運行一些示例程序來弄清這種問題的來龍去脈。根據以往經驗,Flex3 的Halo在處理顯示列表的時候隱藏了大量的實現細節和不良設計。然而一旦你開始使用新的Spark架構后,你就得以近距離的面對這些實現細節—Halo 究竟在私底下干了什么,而且你會體會到為什么說Spark對于顯示列表的處理更為“直白”。

    “elements”是一個關鍵性的問題。elements是何物?它同child是否是一回事?剛開始的時候我曾武斷的認為elements不 過是children的另一種說法。通過反復梳理組件中所有的elements和children,我發覺在新的容器類(也包括一些經過改良的傳統容器) 某些似乎是理所當然應該具備的方法消失了。如果沒有getElements(),我該如何獲取elements的數目呢?我能否把 getChildren() 的返回結果作為IVisualElement來對待。這令我十分糾結。

    困擾的我于是開始認真閱讀學習API文檔,Flex的源碼以及相關的博客文章。我也曾嘗試解讀一些博主發布的關于Flex4新特性的幻燈片。然而事實證明脫離講解而孤立的看幻燈片作用相當有限。

    最后,我拼湊了一些言簡意賅的示例。這些示例將帶領我了解有關elements的全新知識,告訴我那些在新的Spark容器背后發生的故事。

    言歸正傳,首先從問題開始。問題一,“應該如何獲得Spark 容器的全部elements?”我曾想當然的認為是通過一個類似Flex3中的getChildren() 的方法。然而實際上我們需要通過兩個Property來達到這個目的:numElements & numChildren 。可以通過對numElements計數的循環語句配合getElementAt() 來實現遍歷容器elements或特定訪問。這種方式還比較直觀。問題二,“element和child的區別何在?”,讓我們來看看兩者的差異。

    語義上,element簡單的說就是實現了IVisualElement接口的任意型別。child是指擴展了DisplayObject類的任 意型別。判斷某個組件是element還是child亦或兩者都是的關鍵在于以下幾點。UIComponent(所有Flex組件的基類:譯者注)是由 DisplayObject擴展而來,故所有UIComponent都是DisplayObject,也就是說UIComponent都是 children。UIComponent同時也實現了IVisualElement接口,因而所有的UIComponent也可以被作為 elements看待。但這并不是說所有的DisplayObjects(文中所言的DisplayObject一般指擴展于DisplayObject 的子類,譯者注)都是elements。容器中的DisplayObject對象是該無疑是容器的child。而只有當此DisplayObject對象 同時也實現了IVisualElement接口時它才是容器的element。那么對容器而言,DisplayObject什么情況下是child,什么 情況下又是element?通過示例來認識這個問題。

    在首個示例中,我們使用了傳統的Halo容器(這里我們使用的Panel)。Panel擴展與DisplayObject類,所以它可以使用 addChild() 方法。進一步而言,Panel也是Container類的子類(mx.core.Container實現了 IVisualElementContainer接口),它具有addElement() 方法。Container類的IVisualElementContainer接口實現只是基于顯示列表API的門面,所以理論上它和同樣實現了 IVisualElementContainer接口的新式Spark容器具有相同的方法集合。



    于是看起來我們可以任意添加children或element到容器中了。事實卻不是這樣。并非任意型別的element都能被添加(此處 element泛指實現了IVisualElement接口的類)容器中。視覺元素(VisualElements)和圖形元素 (GraphicElements)有一些區別視覺元素(VisualElements)實現了IVisualElement接口,而圖形元素 (GraphicElements)實現的是IVisualElement接口的子接口IGraphicElement。IGraphicElement 接口擴展的新特性為容器獲取信息提供了額外渠道。某些elements(圖形元素是其中之一)無法直接添加至Halo的Panel編譯器會告知“這樣的對 象需事先包裝進一個Group容器中”(實際上錯誤提示應該是在運行時出現,不關編譯器什么事:譯者注)。原因馬上揭曉。

    接下來的示例中,Panel中有若干個UIComponent,其中包括另一個Halo Panel,一個Spark Panel,幾個Halo Button和幾個Spark Button,以及一個包含有子組件的SkinnableContainer(注意: 包含于SkinnableContainer的組件是只屬于SkinnableContainer的children,不是上級容器Panel的 children)。所有組件都繼承于DisplayObject,所以它們都是“children”。點擊“show children”后可以清楚的了解這一點。進一步而言,所有的組件也都是“element”,因為UIComponent實現了 IVisualElement接口。

    看下一個示例。這次我們探討的容器上Spark Group。與前Halo Panel類似,Group繼承于DisplayObjectContainer,它具有addChild() 方法,它同時也實現了IVisualElement接口,所以我們可以用addElement() 方法來IVisualElement對象(elements)。而且Group也接受圖形元素(GraphicElements),比如 spark.primitives.Rect。要知道Rect是無法直接添加到Halo Panel中的。Group是怎么做到這一點的?原因就在于Group知道如何使用一種優化的方式來呈現圖形元素(GraphicElements)。什 么意思?往下讀。

    相對于典型的視覺元素(VisualElements),圖形元素(GraphicElements)與容器的關系更為緊密。其關鍵在于 IGraphicElement接口。上面曾經提到,這個擴展于IVisualElement的接口(此即圖形元素(GraphicElements)可 以通過Group的addElement() 方法來添加至其上的原因所在)。然而由于圖形元素(GraphicElements)不是DisplayObject,所以他們在被“投映”到某個作為他 父對象的DisplayObject前是無法被顯示出來的。基于這個原因,當添加一個“Rectangle”到Group時,需要有 DisplayObject來繪制這個Rectangle。更有效率一點的做法是Group盡可能的復用同一個DisplayObject來繪制多個圖形 元素(GraphicElements)。容器可以使用任何實現了ISharedDisplayObject接口的DisplayObject來繪制圖形 元素(GraphicElements)。第一個示例中的Halo Panel無法使用這種方式來繪制圖形元素(GraphicElements),編譯器會報錯:“必須將其包裝至一個合適的容器中”。而Group支持這 種優化方式,所以能添加圖形元素(GraphicElements)。

    另外需要注意的一點是,有些圖形元素(GraphicElements)的繪制由Group提供DisplayObject來完成,也有的是自行 創建專屬的DisplayObject來完成繪制。IGraphicElement接口甚至允許把對象自己創建的DisplayObject交由容器管理 (換而言之就是以child形態添加的DisplayObject會以IGraphicElement的面貌來繪制自己)。

    這意味著什么?這意味著在接下來的示例中,children的數目和elements的數目是不一樣的。這個示例使用了與第一個示例相同的組件集 合外,還增加了4個矩形圖形元素(GraphicElements)。所有子對象皆為IVisualElement,但不是都可以稱為children。 幾個矩形是圖形元素(GraphicElements),它們并不繼承于DisplayObject。Group不在乎這點,它知道添加 DisplayObject來繪制這些圖形元素(GraphicElements)。由于幾個矩形的尺寸和角度有所不同,所以Group會創建2個新的 DisplayObject來繪制這4個矩形。很酷吧!



    現在來看示例三。我們用一個SkinnableContainer替換先前的Group。SkinnableContainer有和先前相同的子 組件集,它還能利用Skin來增強視覺效果。Skin是SkinnableContainer唯一的child。SkinnableContainer的 默認Skin類由一個矩形和一個被稱為ContentGroup的Group組成。該Group的作用在于規劃出容器內組件的添加位置。

    這個示例證明了這樣的事實,即使SkinnableContainer擁有10個elements,但它只有唯一的child:它自己的 Skin。而且這個Skin也只有唯一的child:名為ContentGroup的Group組件。你也許會感到奇怪:為什么Skin的 children不是2個:其一是ContentGroup,另一個是用于繪制作為邊框的Rectangle的DisplayObject?這是因為 Skin類繼承自Group類,而Group只在它確實需要繪制其包容的圖形元素(GraphicElements)時才會添加 DisplayObject,目前的情況下不需要。Skin類具備直接在其上繪制Rect圖形元素(GraphicElements)的能力,這歸功于 Skin類的上級類Group實現了ISharedDisplayObject接口。這意味著它在需要時能作為共享的DisplayObject來繪制圖 形元素(GraphicElements)。Skin負責管理用于呈現圖形元素(GraphicElements)的DisplayObject,在當前 示例中,Skin自己就是用于繪制的DisplayObject!如果你的自定義Skin中有其它的Rectangle,并將該Skin賦予 SkinnableContainer,這種情況下Skin會判斷是否需要更多的DisplayObject來繪制額外的Rectangle。這時你可能 會發現在Skin的children列表中有更多的child。

    值得注意的是,示例中SkinnableContainer,它的Skin以及Skin的ContentGroup這三者的element列表的 數目是相同的。通過SkinnableContainer的源碼可以知道,numElement的值實際上來源于與之對應的 CurrentContentGroup的numElement。所以基本上對SkinnableContainer的elements的檢索是被重定向 到它的ContentGroup上的。SkinnableContainer的Skin也有類似行為。它繼承于Group,Group的 numElement的值取自其內部的mxmlContent屬性。該屬性是一個保存了Group可視內容children的數組。這兩個屬性與 Panel的RawChildren屬性十分相似,它用于返回Panel上的所有children而不是getChildren()方法返回的僅僅你添加 到Panel上的那些。



    通過以上閱讀,也許起不到撥云見日的效果。但可以讓你明白厘清以下七個類/接口的繼承結構和相互關系是十分有必要的:
    1. DisplayObject
    2. UIComponent
    3. Container
    4. IVisualElement
    5. IGraphicElement
    6. IVisualElementContainer
    7. ISharedDisplayObject

    一旦你掌握它們之間的關系,你就能明白elements 和children的不同。可以肯定的是我在某些問題的認識和闡述上存在很多謬誤之處。如果你發現了這樣的問題望不吝賜教,在評論處寫下您的正確觀點吧。
    主站蜘蛛池模板: 好吊妞在线成人免费| 亚洲精品国产手机| 亚洲电影一区二区| 亚洲日韩AV无码一区二区三区人| 69视频免费在线观看| 亚洲av极品无码专区在线观看| 91精品免费在线观看| 亚洲最大成人网色香蕉| 成年丰满熟妇午夜免费视频| 亚洲gv白嫩小受在线观看| 日韩视频在线观看免费| 亚洲卡一卡2卡三卡4卡无卡三| 国产亚洲综合视频| 91在线视频免费播放| 亚洲欧美日本韩国| 免费国产a国产片高清| 亚洲看片无码在线视频| 国产精品久免费的黄网站| 亚洲中文字幕久久精品蜜桃| 久久国产精品成人片免费| 亚洲专区中文字幕| heyzo亚洲精品日韩| 无码天堂亚洲国产AV| 精品国产亚洲男女在线线电影 | 国产又大又粗又长免费视频| 亚洲综合中文字幕无线码| 亚洲AV无码一区二区三区国产| 亚洲色欲色欱wwW在线| 免费一级毛片不卡不收费| 国产久爱免费精品视频| 亚洲人成网站色在线入口| 亚洲国产人成在线观看69网站 | 免费观看日本污污ww网站一区| h视频在线免费观看| 亚洲男人电影天堂| 亚洲 小说区 图片区 都市| 久久久久久AV无码免费网站 | 美女裸体无遮挡免费视频网站| 无码国产精品一区二区免费I6| 羞羞视频免费网站入口| 亚洲一区二区三区日本久久九|