Dynamically adding child components to Canvas vs Group in flex
I've a custom component where I do some graphics (e.g draw a line) and dynamically add a subcomponent (e.g a label) to it.
If I base the component off Group (which is recommended as per docs since its a spark component) then when I dynamically add a label the graphics part disappears.
However if I base it off Canvas this doesn't happen.
Why is that the case?
Here is the code.
MyComponent.as
public class MyComponent extends Group
{
public var x1:int;
public var y1:int;
public function MyComponent()
{
super();
addEventListener(MouseEvent.MOUSE_DOWN, function(event:MouseEvent):void {
x1 = mouseX;
y1 = mouseY;
});
addEventListener(MouseEvent.MOUSE_MOVE, function(event:MouseEvent):void {
if (event.buttonDown) {
graphics.lineStyle(3, 0x000000);
graphics.moveTo(x1, y1)
graphics.lineTo(mouseX, mouseY);
x1 = mouseX;
开发者_Python百科 y1 = mouseY;
}
});
}
public function addLabel():void
{
var label:Label = new Label();
label.x = 100;
label.y = 100;
label.text = "new label ";
addElement(label); //change to addChild if using Canvas
}
}
Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:local="*">
<s:Panel width="50%" height="50%" verticalCenter="0" horizontalCenter="0" title="Sample app">
<MyComponent id="drawingArea" xmlns="*" width="100%" height="100%" />
<s:controlBarContent>
<s:Button label="Add label" click="drawingArea.addLabel()"/>
</s:controlBarContent>
</s:Panel>
</s:Application>
This might give you some additional insight:
http://www.billdwhite.com/wordpress/?p=296
That is 'normal' as per how the component lifecycle works in Flex. When an invalidateDisplayList
gets called in your function, it redraws everything within it and clears the graphics
. When you add that label, it does invalidate.
If I were you, I'd do something like this:
public class MyComponent extends Group
{
protected var _previousX:int;
protected var _previousY:int;
protected var _drawing:UIComponent;
public function MyComponent()
{
super();
this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
this.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
public function addLabel():void
{
var label:Label = new Label();
label.x = 100;
label.y = 100;
label.text = "new label ";
addElement(label);
}
override protected function createChildren():void
{
super.createChildren();
if(!this._drawing)
{
this._drawing = new UIComponent();
this._drawing.percentWidth = 100;
this._drawing.percentHeight = 100;
this.addElement(this._drawing);
}
}
protected function onMouseDown(e:MouseEvent):void
{
this._previousX = e.localX;
this._previousY = e.localY;
this.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
protected function onMouseUp(e:MouseEvent):void
{
this.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
protected function onMouseDown(e:MouseEvent):void
{
this._drawing.graphics.lineStyle(3, 0x000000);
this._drawing.graphics.moveTo(this._previousX, this._previousY);
this._drawing.graphics.lineTo(e.localX, e.localY);
this._previousX = e.localX;
this._previousY = e.localY;
}
}
This is untested, but I think you get the idea. You should also read up on component lifecycles and really think about what behavior that you're trying to accomplish by trying to abstract it as data (I'm not a fan of the 'addLabel' function for instance :P).
精彩评论