6 Replies Latest reply on Jan 11, 2011 2:22 AM by Joerg Stahlmann

    Problem with ButtonSkin and AS3

    Joerg Stahlmann Level 1

      Hello,

      I'm having problems to make use of my own IconButtonSkin.mxml in a new ActionScript3 Class.

      I can use the ButtonSkin in the same mxml - file, even in the ActionScript, but in a new ActionScript3 Class I'm getting an Error.

      Its kinda hard for me to explain so I'll post some snippets.

       

      The following code works:

      The Style with the IconButton skin-class

       

      <fx:Style>
                @namespace s "library://ns.adobe.com/flex/spark";
                @namespace mx "library://ns.adobe.com/flex/mx";
                @namespace local "*";
      
                local|IconButton {
                     skin-class: ClassReference("IconButtonSkin");
                }
      </fx:Style>
      
      

       

       

      The Container with the first IconButton:

       

      <s:BorderContainer width="186" dropShadowVisible="true" horizontalCenter="0" id="borderBox" borderVisible="true" left="0" right="0" top="0" bottom="0">
                <s:VGroup width="100%" height="100%" horizontalAlign="center" id="grpBox">
                     <local:IconButton 
                          label="Run" 
                          id="runApp" 
                          width="180" 
                          height="30" 
                          top="1"
                          icon="{delIcon}" 
                          horizontalCenter="0"
                          click="runAppHandler()"
                          />     
                </s:VGroup>
      </s:BorderContainer>
      
      

       

       

      The ActionScript, as you can see it is able to set an Icon via iconElement wich means the ButtonSkin is activ, because the runApp-Button is refered to local:IconButton:

       

      
      [Bindable()]
      [Embed('delete2.png')]
      public var delIcon:Class;
                     
      [Bindable()]
      [Embed('add2.png')]
      public var addIcon:Class;
      
      
      
      private var _addBtn:AddButtons;
      
      
      
      
      public function init():void{
           _addBtn = new AddButtons(grpBox); // grpBox is the ID of the VGroup!
      }
      
      public function runAppHandler():void {
            runApp.label = "Add";
            runApp.iconElement.source = addIcon;
            _addBtn.create();                    
      }
      
      

       

       

      Now I'm trying to add a new Button in a new AS-Class (Button is actually added to the VGroup but I'm not able to set an icon):

       

       

      package {
           import mx.controls.Button;
           import spark.components.VGroup;
           public class AddButtons {
                [Bindable()]
                [Embed('greenlight.png')]
                public var newIcon:Class;
      
                public var grpBox:VGroup;
                public var newBtn:IconButton;
                
                public function AddButtons(val:VGroup) {
                     grpBox = new VGroup();
                     grpBox = val;
                }
      
                public function create():void {
                     newBtn = new IconButton();
                     newBtn.label ="neuer Knopf";
                     newBtn.width = 180;
                     newBtn.height = 30;
                     newBtn.iconElement.source = newIcon; // This is causing the Error!
                     grpBox.addElement(newBtn);
                }
           }
      }
      
      

       

       

      And finally I will post the Error message wich pops up by clicking the Add-Button (when the create function is called)

       

       

      TypeError: Error #1009: Cannot access a property or method of a null object reference.

           at AddButtons/create()[/Users/.../workspace/Flash-Builder/ButtonTest/src/AddButtons.as:23]

       

       

       

      I know this is a lot of stuff to read! But it would be really really nice if someone could help me with this!

      Basicly I think I have to figure out how to make the new IconButton to the local:IconButton referenz?

       

      thx in advance!

        • 1. Re: Problem with ButtonSkin and AS3
          drkstr_1 Level 4

          It's because a SkinPart isn't instantiated instantly. You have to wait for the SkinPart to be attached before you can assign properties on it.

           

          Instead of setting the source directly on the skin part, assign and store the value in your IconButton and update the SkinPart when it's available (IE. after a call to partAdded)

           

                  override protected function partAdded(partName:String, instance:Object) : void
                  {
                      super.partAdded(partName, instance);
                      
                      if(instance == this.iconElement)
                      {
                          this.iconElement.source = this.icon;
                      }
                  }
          
          
          1 person found this helpful
          • 2. Re: Problem with ButtonSkin and AS3
            Joerg Stahlmann Level 1

            Hello and thx for your reply!

            I have this IconButton Class:

            public class IconButton extends Button{
                      public function IconButton(){
                           super();
                      }
                      private var _icon:Class;
                      
                      [Bindable]
                      public function get icon():Class{
                           return _icon;
                      }
                      
                      public function set icon(val:Class):void{
                           _icon = val;
                           
                           if (iconElement != null)
                                iconElement.source = _icon;
                      }
            
                      [SkinPart(required="false")]
                      public var iconElement:BitmapImage;
            
                      override protected function partAdded(partName:String, instance:Object):void{
                           super.partAdded(partName, instance);
                      
                           if (icon !== null && instance == iconElement)
                                iconElement.source = icon;
                      }
                 }
            }
            
            

             

            I thought the partAdded function is called automaticly by creating a new IconButton Object?

            If not how do I have to call this? The point is, I can change the style of the IconButton and its works, so the skin of the new IconButton is correct. Only the iconElement is a null object reference.

             

            thx in advance!

            • 3. Re: Problem with ButtonSkin and AS3
              drkstr_1 Level 4

              partAdded is called automatically, but not when the component is first initialized. It get's called during the skinning stage, which happens some time after it's added to the display list. You need to wait until the skin part is created before you do anything on it.

              1 person found this helpful
              • 4. Re: Problem with ButtonSkin and AS3
                Joerg Stahlmann Level 1

                Hi,

                sorry I dont get it...

                You mean that I have to add the iconElement at a later stage of the script?

                • 5. Re: Problem with ButtonSkin and AS3
                  drkstr_1 Level 4

                  No, I'm saying that iconElements gets automatically added later on in the component life-cycle.

                   

                  So at this point...

                   

                   newBtn = new IconButton();
                   newBtn.iconElement.source = newIcon;

                   

                  iconElement would still be null.

                   

                  You need to wait until IconButton creates the skin part as part of it's creation policy.

                   

                  For example...

                   

                  package
                  {
                       import mx.controls.Image;
                       
                       import spark.components.Button;
                       
                       public class IconButton extends Button
                       {
                            [SkinPart]
                            public var iconElement:Image;
                            
                            private var _icon:Object;
                  
                            public function get icon():Object
                            {
                                 return _icon;
                            }
                  
                            public function set icon(value:Object):void
                            {
                                 _icon = value;
                                 
                                 if(this.iconElement)
                                      this.iconElement.source = value;
                            }
                            
                            override protected function partAdded(partName:String, instance:Object):void
                            {
                                 super.partAdded(partName, instance);
                                 
                                 if(instance == this.iconElement)
                                 {
                                      this.iconElement.source = this.icon;
                                 }
                            }
                  
                       }
                  }
                  

                   

                  Then you would use it like this...

                   newBtn = new IconButton();
                   newBtn.icon = newIcon;

                  • 6. Re: Problem with ButtonSkin and AS3
                    Joerg Stahlmann Level 1

                    Arg!

                    Thx,

                    newBtn.icon = newIcon;

                    Thats it!