当前位置: BOLT界面引擎 > 知识库文章 > SetEnable和SetChildrenEnable的使用和注意事项

SetEnable和SetChildrenEnable的使用和注意事项

作者:李亚星

如果对这两个函数比较熟悉的,可以只看最后的加粗的几条内容;如果还不熟悉,或者有疑惑的,建议有时间从头看一下,尤其是里面的例子,重点内容我都用青绿色背景标注出来了。

 

先明确几个概念

 

一个Objectenable会涉及到下面三个概念:

u  内部enable(由SetEnable改变,由Object自身控制)

u  外部enable(由SetChildrenEnable改变,由Object的直接和间接Father来控制)

u  真实enable,由内部enable和外部enable同时制约,只有两者都enable的时候,Object才真实enable,否则为disable

 

之所以后来提供了SetChildrenEnable,是基于下面的需求:当disable一个Object时候,也想disableObject的所有孩子,类似Windows下面窗口的父子关系,当父窗口disable时候,子窗口(父子关系,非拥有者关系)也都会被disable,但是当父窗口再次enable时候,它下面的子窗口,假如之前enable的话,会变得enable;而之前disable的话,也不会随着父窗口的enable而变得enable,也就是满足下面的要点:

 

a)         父窗口enable,子窗口才有可能enable;而父窗口disable,那么所有子窗口都会disable

b)         子窗口的自身enable状态,由EnableWindow或者相关函数来改变

 

XLUE里面的父子关系没有windows下面的限制严格,父Object的内部enable状态,并不影响子Objectenable状态,也就是对父Object调用SetEnable,并不会改变子ObjectEnable状态,但是为了达到windows下面父子窗口的效果,就有了SetChildrenEnable的诞生

 

那么对于每个Object,想达到上述效果,有以下两种方案

B. 递归调用每个子ObjectSetEnable,这样虽然可以达到目的,但是会导致所有子Object的自身的enable状态的丢失, 所有子Object要么全部enable,要么全部disable,很不方便

 

C. 直接调用SetChildrenEnable,会改变该Object的所有子Object的外部enable状态,也就是说,对于一个Object,如果它的直接father、间接Father……直到根Object只要有一个Object调用了SetChildEnable(false),那么该Object的外部enable状态都是false,也就是该Object将被disable

 

好了,如果想到达windows下面的父子窗口关系那样的效果,应该在对一个Object调用SetEnable(false)时候,同时调用SetChildrenEnable(false);想设置为enable亦然。这种特性对于控件开发来说很重要,因为控件的效果,应该是自己disable的时候,会同时disable控件定义下面的所有子objectobjtemplate节点里面定义的那些obj),但是很不幸,XLUE内部并没有对control做特殊处理,controlcontrol定义里面的objtemplate里面定义的子Object,和control使用者在control类型的obj下面添加的子Object,并没有什么不同(也就是示例代码中的idbkgobjectidtitleobject),所以为了避免这种尴尬,应该在control定义里面的objtemplate里面,先定义一个顶级的LayoutObject类型的object(示例代码中的idctrlobject),然后对该Object调用SetChildrenEnable,这样就不会disable control使用者的子Object

 

所以现在control的实现者,为了达到这种效果,一般有两种做法:

A.   自己实现了一个方法Enable代替control本身的SetEnable,然后根据传进来的参数,disable自己,同时disable自己的所有孩子,但是这种做法有很多弊端:

 

a)         使得control类型的obj和普通的obj的接口不一致,没有良好的正交性,对于普通的object来说,SetEnable会隐藏该Object,但是假如该object的类型是一个control,那么SetEnable就无效了,要调用Enable或者其它的方法

b)         假如contorl类型的obj,是由于其father调用了SetChildrenEnable导致的该controldisable,那么该control的孩子就不能达到被disable的目的了

 

B.   control定义里面,响应事件OnEnableChangeOnEnableChange事件是新增加的每个Object都具有的基础事件),在里面根据当前的状态,调用SetChildrenEnable或者挨个disableObject,这样的话,实现起来非常简洁、明了,并且没有第一个方法里面的两个缺点

 

C.    终极方法,由引擎内部自动判断,假如是control,在调用SetEnable时候,同时调用SetChildrenEnable,但是这样牺牲了control定义的灵活性,暂时不会支持

 

 

下面是一段示例代码:

 

Control定义如下:

<control class=”button”>

         <method_def>

                   <Enable>

                            …

                            self:SetEnable(isEnable)

                            local ctrl = self:GetControlObject(“ctrl”)   //注意这里的设置操作,对ctrl进行SetChildrenEnable,而不是对self调用SetChildrenEnable

                            ctrl:SetChildrenEnable(isEnable)

 

                   </ Enable >

         <objtemplate>

                   <obj id=”ctrl” class=”LayoutObject”>        //注意这里的结构,ctrl是一个control定义里面的根object

                            <children>

                                     <obj id=”bkg” class=”ImageObject”>

                                              …

                                     </obj>

                            </children>

                   </obj>

                   <eventlist>

                            <event name="OnEnableChange">

                                     local arg = {...}

                                     local isEnable = arg[2]

                                     local self = arg[1]

                                              

                                     local ctrl = self:GetControlObject(“ctrl”)   //注意这里的设置操作,对ctrl进行SetChildrenEnable,而不是对self调用SetChildrenEnable

                                     ctrl:SetChildrenEnable (isEnable)

                            </event>

                   </eventlist>

         </objtemplate>

</control>

 

 

Control使用者使用如下

<obj id=”close” class=”button”>

         <children>

                   <obj id=”title” class=”TextObject”>

                            …

                   </obj>

         </children>

</obj>

 

 

好吧,总结一下要点:

一、             Object的内部enable状态不会影响子Objectenable状态,也就是对父Object调用SetEnable,不会影响子ObjectEnable状态

 

二、             Object默认状态是enable

 

三、             对于一个Object来说,外部Enable状态受所有父Object(包括直接和多个间接父Object)的SetChildrenEnable影响,只要有一个父Object调用过SetChildrenEnable(false),那么该object的外部enable状态就是false,该object也就被disable

 

四、             只有当一个Obejct的内部enable状态和外部enable状态都为true时候,该objectenable,可就是真实enable状态为true

 

五、             对一个Object调用SetChildrenEnable,不会改变自己的任何Enable状态,只会改变自己所有孩子的外部Enable状态

 

六、             对于一个Object来说,其不同的父Object(直接和间接)调用SetChildrenEnable,并不会相互干扰;比如AB的父,BC的父,B调用了SetChildrenEnable (false),导致Cdisable,这时候A调用SetChildrenEnabletrue),那么C照样还是被disable了,只有B再次调用SetChildrenEnable (true)C才会enable,解铃还须系铃人

 

七、             ObjectGetEnable ()方法返回的是该Object的真实Enable状态

 

八、             每个Object都有OnEnableChange事件,该事件只在该Object真实Enable状态发生改变时候,才会触发

 

九、             SetEnable目前只接收一个参数,表示是否需要enable当前的object

 

十、             control里面的objtemplate里面定义的子Object(如上面例子中的bkg),和control使用者在control类型的obj下面添加的子Object(如上面例子中的title),都是control本身object(如上面例子中的close)的子Object,在该obj看来,并没有什么区别,SetChildrenEnable会对这些子Object都有效,所以要切记下面两点

 

u  对于control开发者来说,control里面调用SetchildrenEnable,不止会影响自己定义里面的子object,还会影响control使用者里面的子object,如上面例子中的title,所以建议定义一个顶级的LayoutObject类型的object,然后对该Object调用SetChildrenEnable

u  对于control使用者来说,如果control下面放了子obj,那么子obj就有可能被不完善的父obj disable,导致不可预期的状态,所以请慎重用controlfather,如果出现Enable状态不对,记得确认control的实现没有问题- -

 

十一、      control定义时候,为了模拟windows下面的窗口父子关系,可以通过增加Enable方法或者相应OnEnableChange事件来实现,强烈推荐使用后者,同时注意第七条里面的注意事项

 

 

目前就想到了这么多内容,这些问题也是平时大家常问的,虽然看起来很多,其实很简单。接下来我们会陆续的对一些使用XLUE常出错、容易出错和大家问的比较多的问题和注意事项,以解疑形式总结出来,如果还有不清楚的,及时联系我们。

 

 

---------------------------------------------------------

李亚星

 

 

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