Connecting lines (while dragging) in Flex/Actionsc

2019-07-15 09:26发布

问题:

I have a mx:Canvas element that contains several mx:Panel elements. I want to be able to draw a line connecting two such mx:Panel's in such a way that the line continues to connect the two mx:Panels when one or both get dragged around. It seems like something that should be trivial to do, but I haven't been able to figure it out.

In effect, this is the problem.

alt text http://img150.imageshack.us/img150/5656/ishot1eu3.jpg

Since the updates only occur when the Panel reaches it's final position, as soon as you start dragging the "B" panel, you are left with a dangling line:

alt text http://img212.imageshack.us/img212/4296/ishot2qi6.jpg

A possible solution, as suggested below, would be to override the updateDisplayList() method of the mx:Canvas component. Unfortunately, that only updates the drawing after the dragging, and not while in motion. Listening to the "xChanged" and "yChanged" events in the Panel produces the same results as overriding the updateDisplayList().

The final solution, as pointed out below, requires dispatching the move events from the moving Panel to the Canvas on which it is moving. This forces the lines to get redrawn throughout the whole motion.

Thanks for all the help!

回答1:

"I've tried overriding the updateDisplayList() method of the mx:Canvas component but that seems to only update the drawing after the dragging. I would like for the line to follow the mx:Panel as it is being dragged."

You can listen to MoveEvent.MOVE events in the Panels and have the handler call for the redrawing of the lines, and then have the Panels dispatch these events while they are being dragged by listening for MouseEvent.MOUSE_MOVE events in the stage and dispatching the MOVE event in the handler (attach this handler to the stage in the Panel's MouseEvent.MOUSE_DOWN event handler, along with a handler for MouseEvent.MOUSE_UP (attached to the stage as well) -- then remove both of these event listeners from the stage in the MOUSE_UP handler.)

Here's an example (this would be in the Panel subclass:)

private function attachListeners():void
{
    this.addEventListener(MouseEvent.MOUSE_DOWN, selfMouseDownHandler, false,0,true);
    this.addEventListener(MoveEvent.MOVE, selfMoveHandler, false,0,true);
}

private function selfMoveHandler(event:MoveEvent):void
{
    redrawConnectedLinks();
}

private function selfMouseDownHandler(event:MouseEvent):void
{
    stage.addEventListener(MouseEvent.MOUSE_UP, stageMouseUpHandler, false,0,true);
    stage.addEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler, false,0,true);
}

private function stageMouseUpHandler(event:MouseEvent):void
{
    stage.removeEventListener(MouseEvent.MOUSE_UP, stageMouseUpHandler, false);
    stage.removeEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler, false);
}

private function stageMouseMoveHandler(event:MouseEvent):void
{
    dispatchEvent(new MoveEvent(MoveEvent.MOVE));
}


回答2:

flexwires is an open source project to implement this type of "connected lines" UI paradigm in Flex. It might just fit your needs.



回答3:

You'd want to override the UIComponent method updateDisplayList() on the Canvas and do your drawing in there.

This is assuming you are familiar with line drawing in AS3 in general.



回答4:

Can't you use bind functionality here? the end point of the line bound to the center of the circle?



回答5:

New to flash/flex and had a similar problem. I solved it by attaching an event listener to the Enter_Frame event. I am not sure if this is the most efficient solution since it redraws even if the objects have not moved but it worked for me:

    import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;

public class Association extends Sprite
{
    private var t1:DisplayObject;
    private var t2:DisplayObject;
    //Connects two objects
    public function Association(t1:DisplayObject, t2:DisplayObject)
    {
        this.t1=t1;
        this.t2=t2;
        this.addEventListener(Event.ENTER_FRAME, redraw)
        super();
    }

    public function redraw(event:Event):void
    {
        graphics.clear();
        graphics.lineStyle(2,0x000000);
        graphics.moveTo(t1.x,t1.y);
        graphics.lineTo(t2.x,t2.y);
    }

}