The NoteBook of EricKong

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks
    复合组件是指包含多个组件的组件。这些组件可以是图形资源或者是图形资源同组件类的合并。比如,创建包括按钮和文本域(text field)的组件,或者,组件包含一个按钮,一个
文本域以及一个校验器(validator) 。
    在创建复合组件时,应当在组件类的内部实例化这些控件。假设这些控件有图形资源,那就必须在类文件中规划所引入的控件的布局,以及设置一些属性,诸如缺省值之类。必须确保
引入符合组件所需的所有类。
    如果组件类是从比较基础的类扩展,比如UIComponent,而不是从像Button这样的控件类扩展的,那么就必须实例化自定义组件中的每个子控件,并管理它们在屏幕上的显示。
    复合组件中单个组件的属性不能从MXML 制作环境中访问,除非设计上允许这么做。例如,如果创建一个从UIComponent扩展的组件,并在这个组件中使用了一个Button 和一个TextArea组件,那么就不能在 MXML 标记中设置 Button 控件的 label 文本,原因就是这个组件不是直接从 Button 类扩展的。

创建组件

这个例子组件被称为 ModalText,在 ModalText.as 文件中定义,组合了一个 Button 控件和一个TextArea 控件。用Button 控件来控制是否允许在 TextArea 控件中进行输入。 
 
为复合组件定义时间监听器
自定义组件通过实现 createChildren()方法来创建子组件,如下面代码所示: 
override protected function createChildren():void { 
    
super.createChildren(); 
    
// Create and initialize the TextArea control.         
    if (!text_mc)     { 
        text_mc 
= new TextArea(); 
                 
        text_mc.addEventListener(
"change", handleChangeEvent); 
        addChild(text_mc);     
    } 
    
// Create and initialize the Button control.         
    if (!mode_mc)     {     
        mode_mc 
= new Button(); 
                 
        mode_mc.addEventListener(
"click", handleClickEvent); 
        addChild(mode_mc); 
    } 

 

     createChildren()方法中也包含对 addEventListener()方法的调用,用这个方法为TextArea 控件所产生的 change 事件以及 Button 控件所产生的 click 事件注册监听器。这些事
件监听器定义在 ModalText 类中,如下面例子所示: 
// Handle events that are dispatched by the children. 
private function handleChangeEvent(eventObj:Event):void { 
        dispatchEvent(
new Event("change")); 

 
// Handle events that are dispatched by the children. 
private function handleClickEvent(eventObj:Event):void { 
        text_mc.editable 
= !text_mc.editable; 

     可在复合组件中处理子组件所分发的事件。在这个例子中,Button 控件的 click 事件的事件监听器被定义在复合组件类中,用来控制 TextArea 控件的 editable 属性。
     但是,如果子组件分发了一个事件,并且希望在组件之外可以有时机来处理这个事件,那么就要在组件定义中增加逻辑来广播这个事件。注意,TextArea 控件的 change 事件监听器中重新广播了这个事件。这就使运用这个组件的应用也能处理这个事件,如下面的例子所示:

<?xml version="1.0"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:MyComp="myComponents.*"> 
    
<mx:Script> 
        
<![CDATA[  
            import flash.events.Event; 
            function handleText(eventObj:Event) 
            { 
                 
            } 
        
]]> 
    
</mx:Script> 
    
<MyComp:ModalText change="handleText(event);"/> 
</mx:Application> 

创建ModalText 组件
下面的例子代码实现了 ModalText 组件的类定义。
  ModalText 组件是一个包含一个Button 控件和一个 TextArea 控件的复合组件。 这个控件有以下特性: 
1. 缺省情况下不能在TextArea 中进行编辑。
2. 通过点击Button控件去控制TextArea控件的编辑。 
3. 通过使用控件的textPlacement 属性来控制TextArea显示在控件的左边还是右边。 
4. 编辑控件的textPlacement属性将会分发placementChanged 事件。 
5. 在程序中使用text 属性可以向TextArea 控件写入内容。 
6. 编辑控件的text属性将会分发一个textChanged事件。
7. 编辑TextArea控件的文本将会分发change事件。
8. textPlacement 和text 属性都可以作为数据绑定表达式的源。
9. 可以有选择性地为Button的up,down和over状态设置皮肤。
  下面的例子在MXML文件中使用ModalText控件, 并且将其textPlacement属性设置为left:  
 
<?xml version="1.0"?>  
<!-- asAdvanced/ASAdvancedMainModalText.mxml --> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  xmlns:MyComp="myComponents.*" > 
    
<MyComp:ModalText textPlacement="left" height="40"/> 
</mx:Application> 
 通过处理 placementChanged 事件,来确定 ModalText.textPlacement 属性何时被修改,如下面的例子所示: 
<?xml version="1.0"?>  
<!-- asAdvanced/ASAdvancedMainModalTextEvent.mxml --> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  xmlns:MyComp="myComponents.*" > 
    
<mx:Script> 
      
<![CDATA[ 
        import flash.events.Event; 
        private function placementChangedListener(event:Event):void { 
          myEvent.text="placementChanged event occurred - textPlacement = "  
              + myMT.textPlacement as String; 
        } 
      
]]> 
    
</mx:Script> 
    
<MyComp:ModalText id="myMT"   textPlacement="left" height="40" placementChanged="placementChangedListener(event);"/> 
    
<mx:TextArea id="myEvent" width="50%"/>     
    
<mx:Label   text="Change Placement" /> 
    
<mx:Button label="Set Text Placement Right"  click="myMT.textPlacement='right';" /> 
    
<mx:Button label="Set Text Placement Left"   click="myMT.textPlacement='left';" /> 
</mx:Application> 

 下面的例子显示定义控件的 ModalText.as 文件源码:
package myComponents 
{  
    // Import all necessary classes. 
    import mx.core.UIComponent; 
    import mx.controls.Button; 
    import mx.controls.TextArea; 
    import flash.events.Event; 
    import flash.text.TextLineMetrics; 
 
    // ModalText dispatches a change event when the text of the child  
    // TextArea control changes, a textChanged event when you set the text  
    // property of ModalText, and a placementChanged event 
    // when you change the textPlacement property of ModalText.  
    [Event(name="change", type="flash.events.Event")] 
    [Event(name="textChanged", type="flash.events.Event")] 
    [Event(name="placementChanged", type="flash.events.Event")] 
     
    /*** a) Extend UIComponent. ***/ 
    public class ModalText extends UIComponent { 
 
        /*** b) Implement the class constructor. ***/ 
        public function ModalText() { 
            super(); 
        } 
        /*** c) Define variables for the two child components. ***/  
        // Declare two variables for the component children. 
        private var text_mc:TextArea; 
        private var mode_mc:Button; 
        /*** d) Embed new skins used by the Button component. ***/ 
        // You can create a SWF file that contains symbols  with the names   
        // ModalUpSkin, ModalOverSkin, and ModalDownSkin.        
        // If you do not have skins, comment out these lines. 
        [Embed(source="Modal2.swf", symbol="blueCircle")]        
        public var modeUpSkinName:Class; 
     
        [Embed(source="Modal2.swf", symbol="blueCircle")] 
        public var modeOverSkinName:Class; 
 
        [Embed(source="Modal2.swf", symbol="greenSquare")] 
        public var modeDownSkinName:Class; 
 
 
        /*** e) Implement the createChildren() method. ***/ 
        // Test for the existence of the children before creating them. 
        // This is optional, but we do this so a subclass can create a  
        // different child instead. 
        override protected function createChildren():void { 
            super.createChildren(); 
 
            // Create and initialize the TextArea control.       
            if (!text_mc) 
            { 
                text_mc = new TextArea(); 
                text_mc.explicitWidth = 80; 
                text_mc.editable = false; 
                text_mc.text= _text; 
                text_mc.addEventListener("change", handleChangeEvent); 
                addChild(text_mc); 
            } 
 
            // Create and initialize the Button control.         
            if (!mode_mc) 
            {   mode_mc = new Button(); 
                mode_mc.label = "Toggle Editing Mode"; 
                // If you do not have skins available,  
                // comment out these lines. 
                mode_mc.setStyle('overSkin', modeOverSkinName);  
                mode_mc.setStyle('upSkin', modeUpSkinName);  
                mode_mc.setStyle('downSkin', modeDownSkinName);  
                mode_mc.addEventListener("click", handleClickEvent); 
                addChild(mode_mc); 
            } 
        }         
         /*** f) Implement the commitProperties() method. ***/ 
        override protected function commitProperties():void { 
            super.commitProperties(); 
            if (bTextChanged) { 
                bTextChanged = false; 
                text_mc.text = _text; 
                invalidateDisplayList(); 
            } 
        }        
        /*** g) Implement the measure() method. ***/ 
        // The default width is the size of the text plus the button. 
        // The height is dictated by the button. 
        override protected function measure():void { 
            super.measure(); 
 
            // Since the Button control uses skins, get the  
            // measured size of the Button control.  
            var buttonWidth:Number = mode_mc.getExplicitOrMeasuredWidth(); 
            var buttonHeight:Number = mode_mc.getExplicitOrMeasuredHeight(); 
 
            // The default and minimum width are the measuredWidth  
            // of the TextArea control plus the measuredWidth  
            // of the Button control.  
            measuredWidth = measuredMinWidth =  text_mc.measuredWidth + buttonWidth; 
             
            // The default and minimum height are the larger of the  
            // height of the TextArea control or the measuredHeight of the  
            // Button control, plus a 10 pixel border around the text.  
            measuredHeight = measuredMinHeight =   Math.max(mode_mc.measuredHeight,buttonHeight) + 10;      
      } 
        /*** h) Implement the updateDisplayList() method. ***/ 
        // Size the Button control to the size of its label text  
        // plus a 10 pixel border area.  
        // Size the TextArea to the remaining area of the component. 
        // Place the children depending on the setting of  
        // the textPlacement property.  
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { 
            super.updateDisplayList(unscaledWidth, unscaledHeight);          
            // Subtract 1 pixel for the left and right border,  
            // and use a 3 pixel margin on left and right. 
            var usableWidth:Number = unscaledWidth - 8; 
 
            // Subtract 1 pixel for the top and bottom border,  
            // and use a 3 pixel margin on top and bottom. 
            var usableHeight:Number = unscaledHeight - 8; 
             
            // Calculate the size of the Button control based on its text. 
            var lineMetrics:TextLineMetrics = measureText(mode_mc.label); 
            // Add a 10 pixel border area around the text. 
            var buttonWidth: Number = lineMetrics.width + 10; 
            var buttonHeight:Number = lineMetrics.height + 10; 
            mode_mc.setActualSize(buttonWidth, buttonHeight);        
             
            // Calculate the size of the text 
            // Allow for a 5 pixel gap between the Button  
            // and the TextArea controls.  
            var textWidth:Number = usableWidth - buttonWidth - 5; 
            var textHeight:Number = usableHeight; 
            text_mc.setActualSize(textWidth, textHeight); 
             
            // Position the controls based on the textPlacement property. 
            if (textPlacement == "left") { 
                text_mc.move(4, 4);                 mode_mc.move(4 + textWidth + 5, 4); 
            } 
            else { 
                mode_mc.move(4, 4); 
                text_mc.move(4 + buttonWidth + 5, 4); 
            }            
            // Draw a simple border around the child components. 
            graphics.lineStyle(1, 0x000000, 1.0); 
            graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);          
        } 
         
        /*** i) Add methods, properties, and metadata. ***/  
        // The general pattern for properties is to specify a private  
        // holder variable. 
        private var _textPlacement:String = "left"; 
        // Create a getter/setter pair for the textPlacement property. 
        public function set textPlacement(p:String):void { 
            _textPlacement = p; 
            invalidateDisplayList(); 
            dispatchEvent(new Event("placementChanged")); 
        } 
 
        // The textPlacement property supports data binding. 
        [Bindable(event="placementChanged")] 
        public function get textPlacement():String { 
            return _textPlacement; 
        } 
         
        private var _text:String = "ModalText"; 
        private var bTextChanged:Boolean = false; 
         
        // Create a getter/setter pair for the text property. 
        public function set text(t:String):void { 
            _text = t; 
            bTextChanged = true;           
            invalidateProperties(); 
            dispatchEvent(new Event("textChanged")); 
        } 
         
        [Bindable(event="textChanged")] 
        public function get text():String { 
                return text_mc.text; 
        } 
         
        // Handle events that are dispatched by the children. 
        private function handleChangeEvent(eventObj:Event):void { 
                dispatchEvent(new Event("change")); 
        } 
 
        // Handle events that are dispatched by the children. 
        private function handleClickEvent(eventObj:Event):void { 
                text_mc.editable = !text_mc.editable; 
        } 
    } 
posted on 2011-07-09 20:57 Eric_jiang 阅读(380) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: