当前位置: BOLT界面引擎 > 知识库文章 > HelloBolt系列教程 > HelloBolt6:使用自定义控件

HelloBolt6:使用自定义控件

作者:Tsukasa

     定义和使用控件。

     定义一个按钮控件,并在界面中使用它。
         
通过之前的例程,我们已经展现了使用Bolt的核心流程,建立无论再复杂的界面,也无非重复上述流程:加入相应的UIObject,处理事件,以及加入动画。
        但是当工程规模,界面复杂程度提升时,仅仅依靠通过Bolt提供的元对象复合的模式无法很好的支持软件工程实践。比如,若主界面包含若干个相对独立同时复杂的模块,如果有多人同时开发,那么只能每个人在主界面对象树上的特定位置工作,之后将代码合并;还有复用性的问题,如果一个较为复杂的复合界面元素在界面中被多次使用,比如最简单的按钮,前面已经看到了一个按钮是由一个LayoutObject加入TextureObject和TextObject复合而成的,如果需要在界面上再加入一个同样的按钮,只能在对象树上再次加入这三个对象,如果需要统一的改变按钮的效果,比如在按钮上添加一个图标,那么就必须在所有使用按钮的地方进行修改。
       为了解决这些问题,Bolt通过自定义控件的方式提供了支持界面模块化这样符合软件工程原则的能力。当一个界面复杂度相当高时,可以将其中相对独立的部分划分为若干自定义控件,开发团队可以分工开发各个控件,之后在主界面中像使用简单元对象一样使用这些控件;当界面中多次使用了相同的复合界面元素时,将之定义为一个控件单独开发,然后在主界面中使用该控件,达到更好的复用。
       HelloBolt6中,又加入了一个按钮,这个按钮相较之前的关闭按钮,更加复杂,除了同样有背景和文本之外,当鼠标悬浮,左键按下时,背景都会发生相应的改变,而且,在UIObjectTree中加入这样一个按钮,相较于之前要加入三个对象的方式,简单如加入了一个ImageObject一样,这样我们就很直接的看到了使用控件带来的好处:
<obj id="userdefine.btn" class="HelloBolt.button">
         <attr>
              <left>260</left>
              <top>214</top>
              <width>126</width>
              <height>44</height>
              <NormalBkgID>button.normal</NormalBkgID>
              <Text>点我</Text>
         </attr>
         <eventlist>
              <event name="OnClick" file="MainWnd.xml.lua" func="userdefine_btn_OnClick"/>
         </eventlist>
     </obj>
以上在对象树模板中添加了一个<obj>节点,与之前不同的是class属性指定的并非Bolt的元对象, 而是一个自定义控件类型名"HelloBolt.button";同样<attr>中除了位置节点之外,还有<NormalBkgID>和<Text>两个不明属性,而在事件定义中,要响应的事件名"OnClick"同样是任何元对象所没有的。这些属性和事件都是在自定义控件中自定义的,在布局中可以和元对象上的属性和事件同样的方法简单配置。
     在Button.xml中定义了这个自定义控件:
     <control class="HelloBolt.button">
在布局xml中以control节点定义控件, class属性指定自定义control的类型名, 也就是可以在对象布局中写入obj节点class属性的类型名。在<attr_def>子节点中,定义control的自定义属性,加入<attr>子节点如:
     <attr name="NormalBkgID" type="string" >
         <default>button.normal</default>
     </attr>
name属性指定属性名,type指定类型如string, int, bool等, default节点可选,用于指定默认值。在布局xml文件中设置自定义属性时,同样通过在<obj>节点的<attr>节点中加入属性名节点实现;而在脚本中访问自定义属性是通过调用自定义控件对象实例上的GetAttribute()接口获取属性表实现的。如自定义的Text属性,在MainWnd.xml中通过<Text>点我</Text>设置, 而在Button.xml.lua中通过如下lua代码访问:

local attr = self:GetAttribute()

     self:SetText(attr.Text)
        

    <method_def>节点中定义自定义控件的自定义方法,与前面说到的自定义动画<method_def>相同。在其中定义的方法可以在自定义控件的实例上作为成员方法被调用,如:
         <SetText file="Button.lua" func="SetText" />
定义名为SetText的自定义方法,在Button.xml.lua中,以:

self:SetText(attr.Text)

调用。
     <event_def>节点定义自定义控件的自定义事件(自定义事件指南), 在MainWnd.xml中的布局中,和Bolt的内置事件一样,通过<event>节点设置响应函数,在Button.xml.lua中通过如下调用触发:

self:FireExtEvent("OnClick")

        
     <objtemplate>节点定义自定义控件的外观布局,可以看到同样是由若干对象复合而成,Bolt中称在自定义控件的<objtemplate>节点中的子对象为控件的内部对象,为他们定义的id称为内部id。当在对象树中加入自定义控件时,实际上是首先加入了一个代表自定义控件的逻辑对象LayoutObject,然后向该LayoutObject上插入在<objtemplate>中定义的内部子对象,与直接在对象树上向该LayoutObject下插入子对象的是等效的。唯一不同的是,内部子对象的内部id会被该LayoutObject的id修饰,因此即便在同一个对象树上加入若干class相同但是id不同的自定义控件对象,内部子对象的内部id在自定义控件的定义中虽然是相同的,但是不会导致它们在对象树上的id相同而冲突。可以通过自定义控件的GetControlObject方法传入内部id索引一个内部对象,如:

self:GetControlObject("text")

    

 
 

  

迅雷公司 版权所有 Copyright 2003-2010 Thunder Inc.All Rights Reserved. 意见反馈:xl7doc@xunlei.com