【发布时间】:2011-01-13 00:22:05
【问题描述】:
我有一个 XML,它有一个属性选项或组合框,解析我需要在我的 flex 中动态创建组件。
Viatropos 提供了一个很棒的代码,但我无法执行它...任何人都可以生成它...谢谢
【问题讨论】:
-
你需要问一个问题...
-
我想创建读取 XML 的组件
标签: xml apache-flex actionscript-3 dynamic
我有一个 XML,它有一个属性选项或组合框,解析我需要在我的 flex 中动态创建组件。
Viatropos 提供了一个很棒的代码,但我无法执行它...任何人都可以生成它...谢谢
【问题讨论】:
标签: xml apache-flex actionscript-3 dynamic
您可以使用以下方式在 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(例如,获取所有属性,或将字符串转换为正确的类型),以及一个采用 XML 文件的 ComponentManifest 类并将其转换为组件。
您还需要确保将 XML 中定义的所有类都导入到 swf 中,否则会抛出该错误。你可以这样做:
import mx.controls.ComboBox; ComboBox;
直接导入,没有第二个 ComboBox 将无法做到。
这应该可以帮助您入门,根据需要填写!
如果您想要更好/更高级的 xml 值解析,请查看 Rubular 与 Regular Expressions 混在一起:)。
【讨论】:
这是@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>
因为我怀疑你可以在手风琴中使用一层嵌套做很多事情。
我将把实现该功能的工作留给你。
【讨论】: