繁体   English   中英

从XML创建Flex组件

[英]Creating Flex components from XML

我有一个XML,它有一个属性选项或组合框,解析我需要在flex中动态创建组件。

Viatropos提供了很棒的代码,但是我无法执行它……任何人都可以产生它……谢谢

您可以使用以下方法在Flex中动态创建组件:

样本数据

<?xml version="1.0" encoding="UTF-8"?>
<components type="array">
    <component type="mx.controls.ComboBox">
        <width>100</width>
        <height>100</height>
        <color isStyle="true">0xff0000</color>
        <prompt>Im a Combo Box!</prompt>
    </component>
    <component type="mx.controls.Button">
        <width>100</width>
        <height>100</height>
        <color isStyle="true">0xff0000</color>
        <label>Im a Button!</label>
    </component>
</components>

示例应用程序

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="creationCompleteHandler()">

    <mx:Script>
        <![CDATA[

            import flash.display.DisplayObject;
            import mx.core.UIComponent;
            import mx.controls.ComboBox; ComboBox;

            protected function creationCompleteHandler():void
            {
                var components:Array = getComponentsFromXML(xml.component);
                var i:int = 0;
                var n:int = components.length;
                for (i; i < n; i++)
                {
                    panel.addChild(components[i] as DisplayObject);
                }
            }

            /**
             *  Parses an XML string, returns array of new components.
             */
            public function getComponentsFromXML(components:XMLList):Array
            {
                var result:Array = [];
                var child:Object;
                var component:UIComponent;
                var type:String;
                var clazz:Class;
                var i:int = 0;
                var n:int = components.length();
                for (i; i < n; i++)
                {
                    child = components[i];
                    type = child.@type;
                    try {
                        clazz = flash.utils.getDefinitionByName(type) as Class;
                    } catch (error:ReferenceError) {
                        traceImportError(type);
                    }

                    component = new clazz(); // dynamic

                    var properties:XMLList = child.elements();
                    var property:XML;
                    var name:String;
                    var value:Object;

                    // for each child node
                    for each (property in properties)
                    {
                        name = property.localName();
                        value = property.toString();
                        // create a more generic method to convert
                        // strings to numbers and whatnot
                        // this is a regular expression matching any digit
                        // check out rubular.com
                        if (/\d+/.test(value.toString()))
                            value = Number(value);

                        if (property.attribute("isStyle") == "true")
                            component.setStyle(name, value);
                        else
                            component[name] = value;
                    }
                    result.push(component);
                }
                return result;
            }

            protected function traceImportError(type:String):void
            {
                trace("Please include the class '" + type + "' in the swf.");
                var names:Array = type.split(".");
                var last:String = names[names.length - 1];
                trace("import " + type + "; " + last + ";");
            }

        ]]>
    </mx:Script>

    <!-- sample data -->
    <mx:XML id="xml" source="components.xml" />

    <!-- sample container -->
    <mx:Panel id="panel" width="100%" height="100%"/>

</mx:Application>

只要您具有XML的定义结构,就可以创建一个XMLUtil以通用地处理xml(例如,获取所有属性,或将字符串转换为正确的类型),以及一个ComponentManifest类,该类获取XML文件并将其转换成组件。

您还需要确保将XML中定义的所有类都导入到swf中,否则它将引发该错误。 您可以这样做:

import mx.controls.ComboBox; ComboBox;

没有第二个ComboBox直接导入将无法完成。

这应该使您入门,并根据需要填写!

如果您想要更好/更高级的xml值解析,请查看Rubular正则表达式 混为一谈

这是@viatropos解决方案的修改版本:

样本数据:

<?xml version="1.0" encoding="UTF-8"?>
<components type="array">
    <component type="mx.controls::ComboBox">
        <width>100</width>
        <height>100</height>
        <color isStyle="true">"0xff0000"</location>
        <label>"Im a Combo Box!"</label>
    </component>
    <component type="mx.controls::Button">
        <width>100</width>
        <height>100</height>
        <color isStyle="true">"0xff0000"</location>
        <label>"Im a Button!"</label>
    </component>
</components>

显然,在此处使用了结束标签的地方有一个错误。

我还在所有字符串值周围添加了引号,以使其更容易识别。

样本(伪)方法: createComponentsFromXML(xml.components)

public function createComponentsFromXML(components:XMLList):void
{
    var child:Object;
    var component:UIComponent;
    var i:int = 0;
    var n:int = components.length();
    for (i; i < n; i++)
    {
        child = components[i];
        var clazz:Class = flash.utils.getDefinitionByName(child.@type);
        component = new clazz(); // dynamic
        var property:Object;
        var value:Object;
        var useIntVal:Boolean;
        var intVal:int;
        // for each child node
        for (property in child.children())
        {
            useIntVal = false;
            value = property.toString();
            if(!(value.substr(1, 2) == '"' AND value.substr(-1, value.length()) == '"')) {
                useIntVal = true;
                intVal = parseInt(value);
            }
            // button["width"] = 100;
            if (property.attribute("isStyle") == "true")
                if(useIntVal) {
                    component.setStyle(property.localName(), intVal);
                } else {
                    component.setStyle(property.localName(), value);
                }
            else {
                if(useIntVal) {
                    component[property.localName()] = intVal;
                } else {
                    component[property.localName()] = value;
                }
            }
        }
    }
}

我实现了对int的转换,以确保检查属性应为字符串还是int。

PS:我现在没有安装Flex,因此您可能会发现一些需要纠正的错误。

在这种情况下,您可能需要这样的XML:

<?xml version="1.0" encoding="UTF-8"?>
<components type="array">
    <component type="mx.controls::ComboBox">
        <properties>
            <width>100</width>
            <height>100</height>
            <color isStyle="true">"0xff0000"</location>
            <label>"Im a Combo Box!"</label>
        </properties>
    </component>
    <component type="mx.controls::Button">
        <properties>
            <width>100</width>
            <height>100</height>
            <color isStyle="true">"0xff0000"</location>
            <label>"Im a Button!"</label>
        </properties>
        <children>
            <!--other children here-->
        </children>
    </component>
</components>

因为我怀疑您可以在手风琴中进行一层嵌套来完成很多工作。

我将留给您实现该功能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM