【问题标题】:Drag and Drop custom titled border box in Flex 4 problemsFlex 4 中的拖放自定义标题边框问题
【发布时间】:2013-04-20 18:34:45
【问题描述】:

希望有 flex 经验的人能够就此提供建议:

所以我有一个小 flex 4 应用程序,它有自定义标题边框容器,我希望能够在容器之间拖放它们但是......当你处理 flex 组件时 d&d 很简单,但是这个自定义标题容器由几个部分组成,例如:标签,边框容器,所以...当我尝试拖放该标题容器时,我无法抓住整个标题容器,而只能抓住其中一个部分(标签或边框框)和当我确实 drop 时,flex 会抛出该元素不在同一组中的错误。

我知道这可能不是对问题的最简单解释,但也许有人已经遇到过这个问题或对此有一些经验,任何帮助表示赞赏。

您好,我已经编辑了我的问题以便更好地理解问题,所以我有这样的自定义标题容器的布局:

----Group A --------------------------------
|                                           |
|   --- Sub Group A --------------------    |
|   |                                   |   |
|   |   --- Item A1 --   --Item A2---   |   |
|   |   |         |     |            |  |   |
|   |   |         |     |            |  |   |
|   |   |-------------   ------------   |   |
|   |                                   |   |
|   |-----------------------------------    |
|                                           |
|-------------------------------------------

----Group B --------------------------------
|                                           |
|   --- Sub Group B --------------------    |
|   |                                   |   |
|   |   --- Item B1 --   --Item B2---   |   |
|   |   |         |      |           |  |   |
|   |   |         |      |           |  |   |
|   |   |-------------   ------------   |   |
|   |                                   |   |
|   |-----------------------------------    |
|                                           |
|-------------------------------------------

我希望 A 组与 B 组能够交换,A 组和 B 组(子组 A 和 B)的孩子必须能够相互交换,最后是子组 A 和 B 也必须是可交换的。现在我已经设法让子组的孩子可以交换,而且子组也可以相互交换,但是...... 有时,当我将子组 A 与 B 交换时,子组 A 会落在子组 B 内。这是一个工作进度,尽管不包括 TitledContainer 并且如果您需要此组件,但我正在使用我的设置发布可运行代码让我知道:

    <?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" minWidth="955" minHeight="600" xmlns:titledContainer="titledContainer.*"
               >
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>

    <fx:Script>
        <![CDATA[
            import mx.core.DragSource;
            import mx.core.IUIComponent;
            import mx.core.IVisualElement;
            import mx.events.DragEvent;
            import mx.managers.DragManager;

            import spark.components.SkinnableContainer;         


            //-------------------------------------------------------------------
            // ITEM BOXES DRAG FUNCTIONS
            //--------------------------------------------------------------------

            private function handleStartDrag( evt:MouseEvent ):void
            {
                // grab the item renderer and relevant data
                var dragItem:IUIComponent = evt.target as IUIComponent;
                var dragSource:DragSource = new DragSource();
                dragSource.addData( dragItem, "item" );
                DragManager.doDrag( dragItem, dragSource, evt );

            }

            protected function handleDragEnter( evt:DragEvent ):void
            {
                if( evt.dragSource.hasFormat( "item" ) )
                    DragManager.acceptDragDrop( evt.target as IUIComponent );

            }

            protected function handleDragDrop( evt:DragEvent ):void
            {
                var dragItem:Object = evt.dragSource.dataForFormat( "item" );
                var dragItemOwner:SkinnableContainer = ( dragItem.owner as
                    SkinnableContainer );
                dragItemOwner.removeElement( dragItem as IVisualElement );
                var targetOwner:SkinnableContainer = ( evt.target as
                    SkinnableContainer );
                targetOwner.addElement( dragItem as IVisualElement );
            }

            //-------------------------------------------------------------------
            // SUB GROUPS CONTAINERS DRAG FUNCTIONS
            //--------------------------------------------------------------------


            private function handleStartDragSub( evt:MouseEvent ):void
            {
                // grab the item renderer and relevant data
                var dragItem:IUIComponent = evt.target as IUIComponent;
                var dragSource:DragSource = new DragSource();
                dragSource.addData( dragItem, "item" );
                DragManager.doDrag( dragItem, dragSource, evt );

            }

            protected function handleDragEnterSub( evt:DragEvent ):void
            {
                if( evt.dragSource.hasFormat( "item" ) )
                    DragManager.acceptDragDrop( evt.target as IUIComponent );

            }

            protected function handleDragDropSub( evt:DragEvent ):void
            {
                var dragItem:Object = evt.dragSource.dataForFormat( "item" );
                var dragItemOwner:SkinnableContainer = ( dragItem.owner as
                    SkinnableContainer );
                dragItemOwner.removeElement( dragItem as IVisualElement );
                var targetOwner:SkinnableContainer = ( evt.target as
                    SkinnableContainer );
                targetOwner.addElement( dragItem as IVisualElement );
            }

        ]]>
    </fx:Script>

    <!-- MAIN CONTAINER ~~~~~~~~~~~~~~~~~~~~~~-->
    <s:SkinnableContainer x="50" y="50" width="100%" height="100%" >
        <s:layout>
            <s:VerticalLayout />
        </s:layout>


        <!-- FIRST ROW ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->

        <s:SkinnableContainer width="100%" >
            <s:layout>
                <s:HorizontalLayout />
            </s:layout>

            <!-- First Group --> 
            <titledContainer:TitledContainer  label="Group A" width="50%" dragEnter="handleDragEnterSub(event)" dragDrop="handleDragDropSub(event)">
                <titledContainer:layout>
                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                </titledContainer:layout>

                <s:Group width="100%"  mouseDown="handleStartDragSub(event);"  >
                    <s:layout>
                        <s:HorizontalLayout />
                    </s:layout>

                    <titledContainer:TitledContainer  label="Sub Group A" width="500" dragEnter="handleDragEnter(event)" dragDrop="handleDragDrop(event)">
                        <titledContainer:layout>
                            <s:HorizontalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                        </titledContainer:layout>

                        <s:Group mouseDown="handleStartDrag(event);">

                            <titledContainer:TitledContainer  label="Item A 1"  >
                                <titledContainer:layout>
                                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                                </titledContainer:layout>
                            </titledContainer:TitledContainer>

                        </s:Group> <!-- Item 1 end-->

                        <s:Group mouseDown="handleStartDrag(event);">

                            <titledContainer:TitledContainer  label="Item A 2"  >
                                <titledContainer:layout>
                                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                                </titledContainer:layout>
                            </titledContainer:TitledContainer>

                        </s:Group> <!-- Item 2 end-->

                    </titledContainer:TitledContainer><!-- Front cover 2 end-->

                </s:Group>

                <s:Group width="100%"  mouseDown="handleStartDragSub(event);"  >
                    <s:layout>
                        <s:HorizontalLayout />
                    </s:layout>

                    <titledContainer:TitledContainer  label="Sub Group B" width="500" dragEnter="handleDragEnter(event)" dragDrop="handleDragDrop(event)">
                        <titledContainer:layout>
                            <s:HorizontalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                        </titledContainer:layout>

                        <s:Group mouseDown="handleStartDrag(event);">

                            <titledContainer:TitledContainer  label="Item B3"  >
                                <titledContainer:layout>
                                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                                </titledContainer:layout>
                            </titledContainer:TitledContainer>

                        </s:Group> <!-- Item 3 end-->

                        <s:Group mouseDown="handleStartDrag(event);">

                            <titledContainer:TitledContainer  label="Item B4"  >
                                <titledContainer:layout>
                                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                                </titledContainer:layout>
                            </titledContainer:TitledContainer>

                        </s:Group> <!-- Item 4 end-->

                    </titledContainer:TitledContainer><!-- Front cover 3 end-->



                </s:Group> 

            </titledContainer:TitledContainer><!-- Front cover 1 end-->

        </s:SkinnableContainer> <!-- first row end-->


    </s:SkinnableContainer>

</s:Application>

请注意,我是 Flex 和 AS3 初学者,所以请对我温柔一点,

问题是:

  1. 能够相互交换组、子组和项目(保持层次结构)并禁止错误放置,即:子组 B 中的子组 A 等。

  2. 单击自定义标题容器时,用户应该能够拖动整个组件而不是标题、边框容器或标题容器内的任何其他内容。

请对初学者温柔一点,我不是要求你为我编写代码,而是如何正确地编写代码,但欢迎提供代码示例,谢谢大家。

【问题讨论】:

  • 您希望能够在容器之间拖放WHAT? Flex 会抛出什么错误?你能分享一些代码吗?也许是一个可运行的样本。
  • 您好,我已经更新了这个问题,现在它更容易理解了,请您看一下并可能对我有所帮助,谢谢。

标签: actionscript-3 apache-flex drag-and-drop flash-builder


【解决方案1】:

纠正显示对象问题

将父自定义容器传递给 startDrag 而不是其元素。为此,您必须像往常一样通过监听来检测拖动

MOUSE_DOWN, MOUSE_MOVE, 

事件。

我猜你已经这样做了,但是按照你可能写的例子

e.target.startDrag(false, new Rectangle(bla, bla));

而不是写

myCustomContainer.startDrag(false, new Rectangle(bla,bla));

为此,有两个先决条件:

1) 如果鼠标在子控件上跳舞,则找到发生拖动的正确容器。 这可以相对容易,如果您的控件是直接 displayObject 后代,在显示列表父树上向上移动,只需检查容器类就足够了。用于检测父母的一个非常基本的代码示例如下:

public function detectMyContainer(t: DisplayObject){

while((t)&&(t !== root)){
    if(t is YourCustomContainer){
         return(t);
    }    
    t = DisplayObject(t).parent;
}
return(null);
}

2) 您不应该在容器的子控件中阻止鼠标按下和鼠标移动事件的传播,因为这会使容器失聪...

现在这将部分解决您的问题,这意味着到目前为止,您正在设法找到正确的父控件并移动它,而不是子控件。

纠正组问题

当你开始拖动一个 displayObject 时,你应该把它放到同一个父对象上。

如果不是,正如你已经看到的那样,as3 会冲你大喊大叫...

如果你想在不同的父对象之间移动显示对象,你应该重写这个行为,你已经按照我将在下面的伪代码的步骤操作:

首先你应该决定你的最终父 DisplayObjectContainer,它包含你将移动孩子的不同父母,通常这是 舞台,但我们将其称为 arena .

让我们将被拖动的对象称为 drag。(是的,我现在缺乏创造力):)。

1) 正确检测拖动。

 look detectMyContainer.

2) 将拖动坐标映射到stage。

 use localToGlobal.

3) 如果arena不是舞台,则将坐标映射到arena。

 use globalToLocal

4) 从父级中移除 drag 并添加到 arena。

 use arena.addChild(drag)

5) 将 drag.x 和 drag.y 设置为竞技场映射坐标。现在你在同一个地方拖了一个更深的父...

6) 在拖动

时开始收听 MOUSE_UP

7) 开始拖动

 use drag.startDrag(...)

8) 当鼠标上升时,查看拖动的放置目标...现在有

 first stopDrag()

9) 适当地检测 dropTarget,它可能不是您猜到的,因此请查看它的类和父类等以确定是否有一个有效的以及哪个。

10) 如果 dropTarget 不存在,将 drag 添加回原来的父级并设置它的原始坐标...(当你习惯了事情,你会在动画这个我打赌)。

11) 现在将 drag 的 arena 坐标映射到 dropTarget

 if arena is not stage make a localToGlobal for drag in arena

 make a globalToLocal for drag global to dropTarget local

12) 从 arena 中移除 drag 并将其添加到其新的父级 dropTarget。

 use dropTarget.addChild(drag)

13) 将 drag.x 和 drag.y 设置为 dropTarget 映射坐标。

就是这样,编码时它会更短,不要害怕......

祝你好运。

【讨论】:

  • 嗨 Ihsan,谢谢你的回答,我相信它可以解决这个问题,我会按照你的指导和报告,谢谢
猜你喜欢
  • 1970-01-01
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2020-01-09
相关资源
最近更新 更多