Wednesday, March 5, 2008

Where's my skin?

If you made it to this post you are probably trying to use a .swc file in a Flex 3 project or something similar. You may have followed the great instructions at this link

When creating programatically a fl.controls.UIScrollBar you get an error similar to the one below at run time. The issue is that the scroll bar's skin related attributes are not initialized properly. I found a workaround to hammer all the bits into place and it involves instantiating an invisible/disabled button and resetting the skin on it.

Workaround

// trick to bring in the skins for the button
var btn:Button = new Button();
btn.setStyle( "upSkin", new Button_upSkin());
btn.enabled = false;
btn.visible = false;
addChild( btn );


Initial error

TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/addChildAt()
at fl.controls::BaseButton/drawBackground()
at fl.controls::BaseButton/draw()
at fl.core::UIComponent/drawNow()
at fl.controls::ScrollBar/draw()
at fl.core::UIComponent/callLaterDispatcher()
TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/addChildAt()
at fl.controls::BaseButton/drawBackground()
at fl.controls::BaseButton/draw()
at fl.core::UIComponent/callLaterDispatcher()
TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/addChildAt()
at fl.controls::BaseButton/drawBackground()
at fl.controls::LabelButton/draw()
at fl.core::UIComponent/callLaterDispatcher()
TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/addChildAt()
at fl.controls::BaseButton/drawBackground()
at fl.controls::BaseButton/draw()
at fl.core::UIComponent/callLaterDispatcher()
TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/addChildAt()
at fl.controls::BaseButton/drawBackground()
at fl.controls::BaseButton/draw()
at fl.core::UIComponent/callLaterDispatcher()

4 comments:

gregbown said...

Wow! Thanks! I added to it for all the states to work.
btn.setStyle( "upSkin", new Button_upSkin());
btn.setStyle( "downSkin", new Button_downSkin());
btn.setStyle( "overSkin", new Button_overSkin());
btn.setStyle( "disabledSkin", new Button_disabledSkin());
btn.setStyle( "selectedUpSkin", new Button_selectedUpSkin());
btn.setStyle( "selectedDownSkin", new Button_selectedDownSkin());
btn.setStyle( "selectedOverSkin", new Button_selectedOverSkin());
btn.setStyle( "selectedDisabledSkin", new Button_selectedDisabledSkin());

BTW, how did you figure this out?
Thanks again for sharing.

gregbown said...

Also in order to get the label to respond to mouseover you need to set your button instance to
myButton.useHandCursor = true
myButton.buttonMode = true
myButton.mouseChildren = false
otherwise you get a hand cursor that appears when hovering over the button but goes away over the button label.

gregbown said...

Adding to this you can also use all the other components like so
check_box = new CheckBox;
check_box.setStyle( "upIcon", new CheckBox_upIcon());
check_box.setStyle( "downIcon", new CheckBox_downIcon());
check_box.setStyle( "overIcon", new CheckBox_overIcon());
check_box.setStyle( "disabledIcon", new CheckBox_disabledIcon());
check_box.setStyle( "selectedDisabledIcon", new CheckBox_selectedDisabledIcon());
check_box.setStyle( "selectedUpIcon", new CheckBox_selectedUpIcon());
check_box.setStyle( "selectedDownIcon", new CheckBox_selectedDownIcon());
check_box.setStyle( "selectedOverIcon", new CheckBox_selectedOverIcon());
check_box.setStyle( "focusRectSkin", new focusRectSkin());
check_box.enabled = false;
check_box.visible = false;
addChild( check_box );

radio_btn = new RadioButton;
radio_btn.setStyle( "upIcon", new RadioButton_upIcon());
radio_btn.setStyle( "downIcon", new RadioButton_downIcon());
radio_btn.setStyle( "overIcon", new RadioButton_overIcon());
radio_btn.setStyle( "disabledIcon", new RadioButton_disabledIcon());
radio_btn.setStyle( "selectedDisabledIcon", new RadioButton_selectedDisabledIcon());
radio_btn.setStyle( "selectedUpIcon", new RadioButton_selectedUpIcon());
radio_btn.setStyle( "selectedDownIcon", new RadioButton_selectedDownIcon());
radio_btn.setStyle( "selectedOverIcon", new RadioButton_selectedOverIcon());
radio_btn.setStyle( "focusRectSkin", new focusRectSkin());
radio_btn.enabled = false;
radio_btn.visible = false;
addChild( radio_btn );

step_box = new NumericStepper;
step_box.setStyle( "upArrowUp", new NumericStepperUpArrow_upSkin());
step_box.setStyle( "upArrowDown", new NumericStepperUpArrow_downSkin());
step_box.setStyle( "upArrowOver", new NumericStepperUpArrow_overSkin());
step_box.setStyle( "upArrowDisabled", new NumericStepperUpArrow_disabledSkin());
step_box.setStyle( "downArrowUp", new NumericStepperDownArrow_upSkin());
step_box.setStyle( "downArrowDown", new NumericStepperDownArrow_downSkin());
step_box.setStyle( "downArrowOver", new NumericStepperDownArrow_overSkin());
step_box.setStyle( "downArrowDisabled", new NumericStepperDownArrow_disabledSkin());
step_box.setStyle( "focusRectSkin", new focusRectSkin());
step_box.enabled = false;
step_box.visible = false;
addChild( step_box );

Combo box is a little more involved
box = new ComboBox;
box.setStyle( "upSkin", new ComboBox_upSkin());
box.setStyle( "downSkin", new ComboBox_downSkin());
box.setStyle( "overSkin", new ComboBox_overSkin());
box.setStyle( "disabledSkin", new ComboBox_disabledSkin());
box.setStyle( "focusRectSkin", new focusRectSkin());
box.setStyle( "List_skin", new List_skin());
box.setStyle( "TextInput_upSkin", new TextInput_upSkin());
box.setStyle( "TextInput_disabledSkin", new TextInput_disabledSkin());
box.setStyle( "CellRenderer_upSkin", new CellRenderer_upSkin());
box.setStyle( "CellRenderer_downSkin", new CellRenderer_downSkin());
box.setStyle( "CellRenderer_overSkin", new CellRenderer_overSkin());
box.setStyle( "CellRenderer_disabledSkin", new CellRenderer_disabledSkin());
box.setStyle( "CellRenderer_selectedUpSkin", new CellRenderer_selectedUpSkin());
box.setStyle( "CellRenderer_selectedDownSkin", new CellRenderer_selectedDownSkin());
box.setStyle( "CellRenderer_selectedOverSkin", new CellRenderer_selectedOverSkin());
box.setStyle( "CellRenderer_selectedDisabledSkin", new CellRenderer_selectedDisabledSkin());
box.setStyle( "ComboBox_disabledSkin", new ComboBox_disabledSkin());
box.setStyle( "ComboBox_downSkin", new ComboBox_downSkin());
box.setStyle( "ComboBox_overSkin", new ComboBox_overSkin());
box.setStyle( "ComboBox_upSkin", new ComboBox_upSkin());
box.setStyle( "ScrollArrowDown_disabledSkin", new ScrollArrowDown_disabledSkin());
box.setStyle( "ScrollArrowDown_downSkin", new ScrollArrowDown_downSkin());
box.setStyle( "ScrollArrowDown_overSkin", new ScrollArrowDown_overSkin());
box.setStyle( "ScrollArrowDown_upSkin", new ScrollArrowDown_upSkin());
box.setStyle( "ScrollArrowUp_disabledSkin", new ScrollArrowUp_disabledSkin());
box.setStyle( "ScrollArrowUp_downSkin", new ScrollArrowUp_downSkin());
box.setStyle( "ScrollArrowUp_overSkin", new ScrollArrowUp_overSkin());
box.setStyle( "ScrollArrowUp_upSkin", new ScrollArrowUp_upSkin());
box.setStyle( "ScrollBar", new ScrollBar());
box.setStyle( "ScrollTrack_skin", new ScrollTrack_skin());
box.setStyle( "ScrollThumb_downSkin", new ScrollThumb_downSkin());
box.setStyle( "ScrollThumb_overSkin", new ScrollThumb_overSkin());
box.setStyle( "ScrollThumb_upSkin", new ScrollThumb_upSkin());
box.enabled = false;
box.visible = false;
addChild( box );

mauricio said...

OH MY GODD!!!!!!!!!!!!!!!! Thank you so much!!!! i have been in a journey of confussion until i got here!!!!!
thank you so so so much!! you have solve a nutcase error!!!!!!!!