`
qzriso
  • 浏览: 236528 次
  • 性别: Icon_minigender_1
  • 来自: ph
社区版块
存档分类
最新评论

利用XML动态创建类

阅读更多

这是一个很好用的技术,我已经在As3中使用它好长一段时间了。使用之前最基本的条件是,你已经知道了类的名字和所属包的的路径,这样就可以轻而易举的在运行时创建类。那么为什么需要这么做呢?有两种情况:一是你有从外部的swf导入的类,二是你已经编译了所有的类,却还想按照XML的配置改变其中的一些类,又不想重新编译。当你用一种CMS生成了你的站点,那么这也是一个非常好用的技术。想象一下,可以把类用于CMS的一段中(a section in the CMS),并且允许编辑从一套“类模板”中选取所需要的。现在,我们有一些在某些地方使用的例子,一起看看我们是如何轻松实现它的。

第一步:创建一个测试类

第一件事情,我们需要做的是创建一个测试类。在你的项目中,创建一个包路径为com.flashartofwar.example的类,如下所示:

  1. package com.flashartofwar.example {
  2.          import flash.display.Sprite;
  3.          /**
  4.           * @author jessefreeman
  5.           */
  6.          public class RedBox extends Sprite {
  7.                   
  8.                   protected var _width:Number = 0;
  9.                   protected var _height:Number = 0;
  10.                   
  11.                   /**
  12.                    * We override the public setter for width so we can redraw
  13.                    * the box when the width is changed.
  14.                    */
  15.                   override public function set width(value : Number) : void {
  16.                            _width = value;
  17.                            trace("Width", super.width);
  18.                            redraw();
  19.                    }
  20.   
  21.                   override public function get width() : Number {
  22.                            return _width;
  23.                    }
  24.   
  25.                   /**
  26.                    * We override the public setter for width so we can redraw
  27.                    * the box when the width is changed.
  28.                    */
  29.                   override public function set height(value : Number) : void {
  30.                            _height = value;
  31.                            redraw();
  32.                    }
  33.   
  34.                   override public function get height() : Number {
  35.                            return _height;
  36.                    }
  37.   
  38.                   public function RedBox() {
  39.                            width = 100;
  40.                            height = 100;
  41.                            redraw();
  42.                    }
  43.                   
  44.                   /**
  45.                    * This simply clears the graphics and redraws the box based
  46.                    * on the new width and height.
  47.                    */               
  48.                   public function redraw():void
  49.                   {
  50.                            graphics.clear();
  51.                            graphics.beginFill(0xFF0000);
  52.                            graphics.drawRect(0, 0, width, height);
  53.                            graphics.endFill();
  54.                    }
  55.           }
  56. }
复制代码

就像你看到的,这个基本的类继承了Sprite,并添加了管理width/height的自定义逻辑,还画了一个shape。我不愿将更多的时间花费在这个类上,它只是一个最基本的例子,任何的类都可以在这里良好的运行。

第2步:建立一个Doc类

现在我们需要一个文档类,来测试我们的RedBox类是否工作。

  1. package {
  2.          import flash.display.StageAlign;
  3.          import flash.display.StageScaleMode;
  4.          import com.flashartofwar.example.RedBox;
  5.          import flash.display.Sprite;
  6.          /**
  7.           * @author jessefreeman
  8.           */
  9.          public class DynamicClassDemo extends Sprite {
  10.                   public function DynamicClassDemo() {
  11.                            configureStage();
  12.                            createRedBox();
  13.                    }
  14.                   
  15.                   private function configureStage() : void {
  16.                            stage.scaleMode = StageScaleMode.NO_SCALE;
  17.                            stage.align = StageAlign.TOP_LEFT;
  18.                    }
  19.   
  20.                   private function createRedBox() : void {
  21.                            var redBox:RedBox = new RedBox();
  22.                            redBox.width = 100;
  23.                            redBox.height = 100;
  24.                            redBox.x = redBox.y = 10;
  25.                            addChild(redBox);
  26.                    }
  27.           }
  28. }
复制代码

同样,这个类也没什么特殊的。我设定了下stage,并建立一个可以创建RedBox的类。如果你运行下,你会看到一个100×100的红色的盒子。到这为止呢,所有的事情看起来都是这么的正确。

第三步:使用getDefinitionByName
接下来,让我们尝试下动态创建RedBox类。我将要使用到一个叫做getDefinitionByName的包方法,它可以通过完整的包路径和类名来查找某个类。把createRedBox方法用以下的代码替换。

  1. private function createRedBox() : void {
  2.          var tempClass : Class = getDefinitionByName("com.flashartofwar.example.RedBox") as Class;
  3.          
  4.          var redBox:RedBox = new tempClass();
  5.          redBox.width = 100;
  6.          redBox.height = 100;
  7.          redBox.x = redBox.y = 10;
  8.          addChild(redBox);
  9. }
复制代码

你也要导入如下:

  1. import flash.utils.getDefinitionByName;
复制代码

好,注意到了吗?我们这里只是简单地用new tempClass()替换了new RedBox(),并在这行之前使用了getDefinitionByName方法。只有这一点改变。我们建立了一个Class类型的持有变量,然后用getDefinitionByName返回了一个com.flashartofwar.example.RedBox类的实例。一旦我们有了一个类自己的引用,那么我们就可以简单地创建新的实例。灵巧的技巧,对吧?同样,我们若不使用As3自己的internal类去到系统里找我们所需要的类,这样写也是可以的,var tempClass:Class =com.flashartofwar.example.RedBox。运行一下,你同样可以看到一个和第2步相同的红色的盒子。
让我们通过XML来创建类吧,你可能会惊讶它有多么简单哦!

第四步:通过XML创建RedBox
现在我们要做与第三步同样的事情,只不过要把类的名字放到XML里。在这里例子里我要做些令人兴奋的

小变化。为什么你不用下面的代码再一次代替createRedBox呢?

  1.          // This is some sample XML data, we can just as easily
  2.          // loda this at runtime instead of compiling it in.
  3.          var xmlData:XML = <boxes base-package="com.flashartofwar.example">
  4.                  <box name="box1" class="RedBox" x="10" y="10" width="100" height="100"/>
  5.                  <box name="box2" class="RedBox" x="120" y="10" width="50" height="100"/>
  6.                  <box name="box3" class="RedBox" x="190" y="10" width="20" height="100"/>
  7.          </boxes>;
  8.          
  9.          // Pull out some core data we need from the xml
  10.          var basePackage:String = xmlData.@["base-package"];
  11.          var boxes:XMLList = xmlData.*;
  12.          var box:XML;
  13.          var boxInstance:DisplayObject;
  14.          
  15.          // Loop through each box node and build it's class
  16.          for each(box in boxes)
  17.          {
  18.                   // It is very important that we use quotes for the class
  19.                   // because it is a reserved word
  20.                   var tempClass : Class = getDefinitionByName(basePackage+"."+box.@["class"]) as Class;        
  21.                   // Here we type box to DisplayObject since we are not
  22.                   // sure what class it actually is
  23.                   boxInstance = new tempClass();
  24.                   boxInstance.x = Number(box.@x);
  25.                   boxInstance.y = Number(box.@y);
  26.                   boxInstance.width = Number(box.@width);
  27.                   boxInstance.height = Number(box.@height);
  28.                   
  29.                   addChild(boxInstance);
  30.           }
  31. }
复制代码

确定你要导入了下面的代码哦:

  1. import flash.display.DisplayObject;
复制代码

这回,我们有很多事情要做了,我添加了一些注释来帮助你。在上面的代码中,我们写了一些xml,并循环每一个box结点。一个好的技巧是,为了减少重复性得写代码,把package名字作为根结点的属性。下一步,你会看到每一个box都有一个名字、一个类、一个x值、一个y值,宽度和高度。最后的事情是,你应该注意我把redBox变量改成boxInstance,并且它现在的类型是DisplayObject类型的。运行下,看看发生了什么。

哦!你会看见如下的错误:

  1. ReferenceError: Error #1065: Variable RedBox is not defined.
  2.         at global/flash.utils::getDefinitionByName()
  3.         at DynamicClassDemo/createRedBox()
  4.         at DynamicClassDemo()
复制代码

在没有定义类型之前,它不再是com.flashartofwar.example.RedBox的引用,所以编译器会忽略导入它。这是在通过XML动态创建class的时候经常出的一个问题,我们不得不要使用一些技巧强制编译器包括这个类。让我们在com.flashartofwar.example包中创建一个叫做IncludeClasses 的新类:

  1. package com.flashartofwar.example {
  2.          /**
  3.           * @author jessefreeman
  4.           */
  5.          public class IncludeClasses {
  6.                   RedBox;
  7.           }
  8. }
复制代码

我知道,你一定认为这太疯狂了吧,但是这就是解决动态创建类的方法。非常简单地把类名字放进一个空类里,编译器就是加载它,即使在这个类里面没有任何的变量被定义。最后的事情是,定义一个该类的变量放到我们的文档类里。这里是代码:

  1. // This class forces the compiler to import your dynamic Classes
  2. var includeClasses:IncludeClasses;
复制代码

并确定你导入了这个:

  1.   
  2. import com.flashartofwar.example.IncludeClasses;
复制代码

现在再次运行你的项目,你会看到3个盒子通过XML动态得被初始化出来。这可不简单哦,你可以自己试着创建一个类,来创建绿盒子和蓝盒子,然后把它们加入到IncludeClasses类里面,然后再在XML文件中配置一下。他们会像红盒子这样被创建出来。当我们知道包路径和类名的时候,我希望使用getDefinitionByName的这个简单的例子可以让我们更简便地创建类。请在评论里自由的发言吧,并讨论你在自己的项目中是如何使用这个技巧的呢。

分享到:
评论

相关推荐

    本示例实现利用 XML 布局文件动态创建CheckBox

    本示例实现利用 XML 布局文件动态创建CheckBox 可以在XML布局文件中先配置一个或若干CheckBox,然后以这些配置为模板来动态创建CheckBox对象

    实现跨frame的js加载xml动态生成的菜单

    真正跨frame的菜单,下载解压可用 技术上是利用js动态创建createPopup来实现的 有兴趣的建议下载看看,有问题可以发邮件到33424103@qq.com

    利用DOM技术对XML文档进行访问与操作

    [实验目的]: 理解应用程序访问与操作XML文档的过程; 掌握用DOM创建XML文档的步骤; 掌握DOM常用类的使用方法 [实验内容] 利用DOM创建如下结构的XML文档(文件名定为:new.xml)

    动态树形结构菜单,从数据库中动态读取节点,通过XML和JS创建树形结构

    从数据岛menuXML中读取数据,从树的根节点开始分析树, 利用 hasChildNodes() [方法:是否含有子节点 ] 判断当前 节点是否有子节点,如果有子节点继续向下分析 childNodes [对象:子节点对象集合] ,否则返回当前分析结果...

    XML学习指南 电子书

    本书还包括了指向Web上大量XML信息的详尽链接集,如果你想要了解基础知识以外的信息,则可以利用这些链接。在本书中将学到什么本书的第一部分(第1章和第2章)提供了对XML的简要介绍,并为学习后续的详细信息做准备...

    XML高级编程

    他们会根据具体情况利用XML解决数据交换的问题并说明具体细节。这条主线的一个题外话就是对无线应用协议(Wireless Application Protocol, WAP)的讨论,它与第14章中XML在无线标记语言(Wireless Markup Language, ...

    Android_和_XML_构建动态用户界面

    为更好地利用本文,您应该使用 Android SDK 来构造 Android ...在此过程中,您将创建自定义和动态的用户界面布局、多线程通信、消息处理程序、以及进程对话框。至少,您将了解 AndroidManifest.xml 和服务器端脚本编写

    XML学习指南经典中文版

    本书还包括了指向Web上大量XML信息的详尽链接集,如果你想要了解基础知识以外的信息,则可以利用这些链接。在本书中将学到什么本书的第一部分(第1章和第2章)提供了对XML的简要介绍,并为学习后续的详细信息做准备...

    Asp.net动态生成html页面

    利用如Dw-Mx这样的工具生成html格式的模板,在需要添加格式的地方加入特殊标记(如$htmlformat$),动态生成文件时利用代码读取此模板,然后获得前台输入的内容,添加到此模板的标记位置中,生成新文件名后写入磁盘,...

    基于Java的XML解析与反射设计模式.doc

    所以在读取大型xml时可以把 xstream与saxparser结合起来使用,用saxparser读取整个xml把核心数据部分让xstrea m来解析成javabean,这样既解决了大数据的问题又利用了xstream快速转化javabean的 优点。 为了利于多...

    JAVA_API1.6文档(中文)

    java.lang 提供利用 Java 编程语言进行程序设计的基础类。 java.lang.annotation 为 Java 编程语言注释设施提供库支持。 java.lang.instrument 提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。 java....

    XML学习指南

    本书还包括了指向Web上大量XML信息的详尽链接集,如果你想要了解基础知识以外的信息,则可以利用这些链接。在本书中将学到什么本书的第一部分(第1章和第2章)提供了对XML的简要介绍,并为学习后续的详细信息做准备...

    无限菜单之 xml+popup 版(IE5.5+)

    这样:使用menu.xsl解析一级xml的内容生成一级菜单,如果该级xml中某节点有子节点,当鼠标经过该节点时,创建当前窗口/Popup窗口的子Popup窗口,使用menu.xsl解析子节点中xml的内容并输出显示到子Popup中,递归,...

    DatabaseParameters.xml

    利用可扩展标记语言存取参数被广泛的使用,我在利用Treeview来读取DatabaseParameters.xml中的数据,获取他的父节点和子节点的数量和信息,使我可以动态的创建treeview控件的Item。这样子的做法方便日后我对treeview...

    java api最新7.0

    java.applet 提供创建 applet 所必需的类和 applet 用来与其 applet 上下文通信的类。 java.awt 包含用于创建用户界面和绘制图形图像的所有类。 java.awt.color 提供用于颜色空间的类。 java.awt.datatransfer 提供...

    JavaAPI1.6中文chm文档 part1

    java.applet 提供创建 applet 所必需的类和 applet 用来与其 applet 上下文通信的类。 java.awt 包含用于创建用户界面和绘制图形图像的所有类。 java.awt.color 提供用于颜色空间的类。 java.awt.datatransfer ...

    [Java参考文档]

    java.applet 提供创建 applet 所必需的类和 applet 用来与其 applet 上下文通信的类。 java.awt 包含用于创建用户界面和绘制图形图像的所有类。 java.awt.color 提供用于颜色空间的类。 java.awt.datatransfer ...

Global site tag (gtag.js) - Google Analytics