Добавление радиокнопки динамически, дважды - ошибка №2025: предоставленный объект DisplayObject должен быть дочерним по отношению к вызывающему.

У меня есть приложение FLEX 4, и у меня возникают проблемы с динамическим добавлением элементов управления пользовательского интерфейса. В основном с переключателями.

Вот пример, демонстрирующий мою проблему:

<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"
    creationPolicy="all"
    >

    <fx:Script>
        <![CDATA[ 
            import mx.containers.Form;
            import mx.containers.Panel;
            import mx.controls.Label;
            import mx.controls.NumericStepper;
            import mx.controls.RadioButton;


            private var theChar:String = "B";

            protected function btnAdd_clickHandler(event:MouseEvent):void
            {                           

                var theForm:Form = new Form();               
                theForm.label = theChar;

                //1. Label
                var myLabel:Label = new Label();
                myLabel.text = "My Label";
                myLabel.width=120;
                theForm.addChild(myLabel);

                //2. Numeric Stepper
                var myNumStepper:NumericStepper = new NumericStepper();
                myNumStepper.id = "numPointHigh" + theChar;
                myNumStepper.name = "numPointHigh" + theChar;
                myNumStepper.minimum = 0;
                myNumStepper.maximum = 120;
                myNumStepper.width = 50;
                myNumStepper.height = 30;
                theForm.addChild(myNumStepper);

                //3. radio button
                var myRadioButton:RadioButton = new RadioButton;
                myRadioButton.id = "myRadioButton" + theChar;
                myRadioButton.name = "myRadioButton" + theChar;
                myRadioButton.label = "my radio button";
                myRadioButton.selected = true;
                theForm.addChild(myRadioButton);

                //4. Panel
                var thePanel:Panel = new Panel();
                thePanel.width = 300;
                thePanel.height = 475;
                thePanel.name=theChar;
                thePanel.title = "My Profile Panel";
                thePanel.setStyle("backgroundColor", "blue");

                //add the form to the panel
                thePanel.addChild(theForm);

                //add the Panel to the list control
                myContainer.addChild(thePanel);

            }

            protected function btnClear_clickHandler(event:MouseEvent):void
            {
                var numChildren:Number = myContainer.numChildren;
                for(var i:Number=numChildren - 1; i > -1; i--){
                    myContainer.removeChildAt(i);
                }
            }

        ]]>
    </fx:Script>

    <mx:VBox width="100%">
        <mx:Panel id="myContainer" />
        <mx:Button id="btnAdd" label="Add a panel" click="btnAdd_clickHandler(event)" color="black"/>
        <mx:Button id="btnClear" label="Clear" click="btnClear_clickHandler(event)" color="black" />
    </mx:VBox>

</s:Application>

^ Запустите это. Нажмите кнопку «Добавить панель». Затем нажмите «Очистить». Затем снова нажмите кнопку «Добавить панель». Вы увидите ошибку:

ArgumentError: Ошибка № 2025: предоставленный объект DisplayObject должен быть дочерним по отношению к вызывающему. в flash.display :: DisplayObjectContainer / getChildIndex () в mx.core :: Container / getChildIndex () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ core \ Container.as: 2833] в mx.containers :: Panel / getChildIndex () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ container \ Panel.as: 1174] в mx.controls :: RadioButtonGroup / widththOrderCompare () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ controls \ RadioButtonGroup.as: 600] в mx.controls :: RadioButtonGroup / widththOrderCompare () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ controls \ RadioButtonGroup.as: 611] в mx.controls :: RadioButtonGroup / widththOrderCompare () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ controls \ RadioButtonGroup.as:611] в массиве $ / _ sort () в массиве / http: //adobe.com/AS3/2006/builtin :: sort () в mx.controls :: RadioButtonGroup / http: //www.adobe. com / 2006 / flex / mx / internal :: addInstance () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ controls \ RadioButtonGroup.as: 465] в mx.controls :: RadioButton / addToGroup () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ controls \ RadioButton.as: 574] в mx.controls :: RadioButton / commitProperties () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ controls \ RadioButton.as: 514] в mx.core :: UIComponent / validateProperties () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ core \ UIComponent.as: 7772] в mx.managers :: LayoutManager / validateProperties () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ manager \ LayoutManager.as:572] в mx.manager :: LayoutManager / doPhasedInstantiation () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ manager \ LayoutManager.as: 730] в mx.managers: : LayoutManager / doPhasedInstantiationCallback () [E: \ dev \ 4.0.0 \ frameworks \ projects \ framework \ src \ mx \ manager \ LayoutManager.as: 1072]

Я не понимаю, почему я не могу повторно добавить переключатель после первого нажатия? Это происходит только тогда, когда у меня есть радиокнопки, добавляемые в форму / панель.

Если вы закомментируете код для переключателя (раздел комментария № 3), вы можете легко повторно добавить панели. Попробуйте, закомментируйте это, и вы сможете без проблем добавлять, повторно добавлять панель:

            //3. radio button
            //var myRadioButton:RadioButton = new RadioButton;
            //myRadioButton.id = "myRadioButton" + theChar;
            //myRadioButton.name = "myRadioButton" + theChar;
            //myRadioButton.label = "my radio button";
            //myRadioButton.selected = true;
            //theForm.addChild(myRadioButton);

Почему это происходит и как это исправить? Почему это происходит только с переключателями? Я могу использовать флажки, текстовые поля, что угодно, и это не вызывает таких исключений ... какие-нибудь идеи?


person D3vtr0n    schedule 02.11.2010    source источник


Ответы (1)


Вы не добавляете свои переключатели в группу переключателей. Начните делать это, и вы перестанете видеть ошибки.

Тем не менее, эта строка для меня загадка:

myList.addChild(thePanel);

Почему вы добавляете дочерние элементы в элемент управления списком? Вы не должны использовать список как контейнер. Он должен фокусироваться только на отображении элементов в вашем DataProvider. Класс списка не имеет возможности позиционировать или размещать элементы, не входящие в dataProvider.

Кроме того, при создании нового RadioButton у вас нет скобок:

var myRadioButton:RadioButton = new RadioButton;

Теоретически это не должно иметь никакого значения, но я всегда предпочитаю оставлять круглые скобки внутри.

Вот рабочий код:

<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"
    creationPolicy="all"
    >

    <fx:Script>
        <![CDATA[ 
            import mx.containers.Form;
            import mx.containers.Panel;
            import mx.controls.Label;
            import mx.controls.NumericStepper;
            import mx.controls.RadioButton;
            import mx.controls.RadioButtonGroup;

            import spark.components.RadioButtonGroup;


            private var theChar:String = "B";

            protected function btnAdd_clickHandler(event:MouseEvent):void
            {                           

                var theForm:Form = new Form();               
                theForm.label = theChar;

                //1. Label
                var myLabel:Label = new Label();
                myLabel.text = "My Label";
                myLabel.width=120;
                theForm.addChild(myLabel);

                //2. Numeric Stepper
                var myNumStepper:NumericStepper = new NumericStepper();
                myNumStepper.id = "numPointHigh" + theChar;
                myNumStepper.name = "numPointHigh" + theChar;
                myNumStepper.minimum = 0;
                myNumStepper.maximum = 120;
                myNumStepper.width = 50;
                myNumStepper.height = 30;
                theForm.addChild(myNumStepper);

                //3. radio button
                var radioButtonGroup : mx.controls.RadioButtonGroup = new mx.controls.RadioButtonGroup();
                var myRadioButton:RadioButton = new RadioButton();
                myRadioButton.id = "myRadioButton" + theChar ;
                myRadioButton.name = "myRadioButton" + theChar ;
                myRadioButton.group = radioButtonGroup ;
                myRadioButton.label = "my radio button";
                myRadioButton.selected = true;
                theForm.addChild(myRadioButton);

                //4. Panel
                var thePanel:Panel = new Panel();
                thePanel.width = 300;
                thePanel.height = 475;
                thePanel.name=theChar;
                thePanel.title = "My Profile Panel";
                thePanel.setStyle("backgroundColor", "blue");

                //add the form to the panel
                thePanel.addChild(theForm);

                //add the Panel to the list control
                myList.addChild(thePanel);

            }

            protected function btnClear_clickHandler(event:MouseEvent):void
            {
                var numChildren:Number = myList.numChildren;
                for(var i:Number=numChildren - 1; i > -1; i--){
                    myList.removeChildAt(i);
                }
            }

        ]]>
    </fx:Script>

    <mx:VBox width="100%">
        <!--<mx:List id="myList" />-->
        <mx:VBox id="myList" />
        <mx:Button id="btnAdd" label="Add a panel" click="btnAdd_clickHandler(event)" color="black"/>
        <mx:Button id="btnClear" label="Clear" click="btnClear_clickHandler(event)" color="black" />
    </mx:VBox>

</s:Application>
person JeffryHouser    schedule 02.11.2010
comment
Я использовал элемент управления списком, когда быстро создал этот пример, чтобы доказать свою проблему. Я переключил его на использование Panel, но его поведение было таким же. Я только что понял, что это исправление на самом деле не объясняет проблему. Почему я могу добавить переключатели в первый раз, но затем нужно использовать RadioButtonGroup при второй загрузке контейнера? Мне странно, что это вообще могло бы работать без RadioButtonGroup? Мне также странно, что в самом сообщении об исключении ничего не упоминается о RadioButtonGroups или даже о самом radioButton. Но если вы посмотрите на классы, вы увидите это. - person D3vtr0n; 04.11.2010
comment
Я не знаю; У объявления нет времени на реконструирование кода переключателя. Но я предполагаю, что это связано с группой переключателей по умолчанию и наличием двух экземпляров компонента с одинаковым именем в одном компоненте. - person JeffryHouser; 04.11.2010