在线文档:
HelloBolt3:使用Bolt的各种UIObject
HelloBolt3
中,在XAR布局中的对象树模板中加入各种UIObject,构成一个较完整的界面。
在前面的HelloBolt2教程中, 已经定义了UIObjectTree Template 和HostWnd Template,并在UIObjectTree Template上加入了一个展示底图的ImageObject。接下来为了丰富界面, 我们继续通过在UIObjectTree Template上加入更多UIObject的方式加入更多界面元素。
为了能在界面正中底图之上显示"
Hello,Bolt!
”
几个大字, 向对象树上加入Bolt提供的展示文本的TextObject类型的UIObject. Bolt的对象树只能有唯一的根对象,在UIObjectTree Template的定义中,与<attr>节点同级的<obj>节点(也就在HelloBolt2中加入的展示底图的ImageObject类型对象)即是对象树的根对象。接下来要加入其他对象,就不能在与根对象相同的层次上插入, 必须将之作为根对象的子对象加入。在布局xml中向一个UIObject上加入子对象,是通过在<obj>节点中的<children>子节点中迭代的加入<obj>节点实现的。进入MainWnd.xml中:
<children>
<obj id="msg" class="TextObject">
如上xml节点,在根对象上加入id为msg , class 为TextObject的子对象。在Bolt中,子对象与父对象的关系表现为:
首先,子对象在对象树上的绝对位置是由子对象对父对象的相对位置决定的,直接指定子对象的位置(通过UIObject的SetObjPos接口和布局xml中<attr>节点中的<left>等节点指定)时,指定的都是子对象对父对象的相对位置,也就是说当父对象的位置发生偏移时,子对象也会相应的偏移同样距离;
第二,子对象在界面上的层次(zorder)默认位于父对象之上,量化的数值是+100,在不显式指定子对象层次(通过UIObject的SetZorder接口和<attr>节点中的<zorder>节点指定)时,子对象在显示时会在其大小范围内覆盖父对象,同时也会影响消息路由,显式指定子对象层次时,指定的也是相对于父对象的相对值(可以为负),比如在zorder节点上指定为-101就表示将子对象置于父对象的层次之下。
在子对象的<obj>中的<attr>下的<left>等属性指定这个文本相对于底图的位置是居于正中的。
TextObject
是Bolt内置的用于展示文本的UIObject,可以指定要显示的文本内容,使用的字体,颜色:
<text>Hello,Bolt!</text>
以上xml节点指定TextObject对象要显示的文本内容;
<textcolor>system.orange</textcolor>
以上xml节点指定TextObject对象的文本颜色。Bolt将颜色作一种资源,引用时可以以资源id的方法指定。要在资源包中加入颜色资源,在res\default目录中加入color.xml转到color.xml中:
<color id="system.orange" red="44" green="151" blue="241" alpha="255" />
以上xml节点定义了id为system.orange的颜色资源。Bolt加载资源包时,会扫描资源包中所有的xml格式文件,一般为了明确资源类型,可以在不同xml中集中定义不同类型的资源,比如这里的color.xml中只定义颜色资源。
回到MainWnd.xml中我们正在关注的TextObject的定义中来:
<font>msg.font</font>
以上xml节点指定TextObject对象的文本字体,字体也是一种资源,msg.font字体在default资源包中的font.xml中定义,xml节点如下:
<font id="default.font" height="14" facename="
微软雅黑" />
其中height属性指定字号,facename指定font face, 系统中安装的字体都可以直接指定。
Bolt
渲染文本时,提供了两种渲染引擎,一是windows GDI,另一种是freetype(字体渲染引擎介绍),因为freetype渲染引擎的效率较高,所以TextObject默认用freetype渲染文本。为了能够使用freetype引擎渲染TextObject,需要在XLGraphic的初始化中初始化freetype。因此,需要在Bolt.cpp的InitXLUE方法中加入如下代码:
param.textType = XLTEXT_TYPE_FREETYPE;
result = XL_SetFreeTypeEnabled(TRUE);
|
回到MainWnd.xml中UIObjectTree上在HelloBolt3中新加入的对象:
<obj id="title" class="CaptionObject">
以上xml节点加入了一个CaptionObject类型的对象。CaptionObject是Bolt内置的控制对象中的一种(Bolt元对象介绍)。不同于ImageObject, TextObject等用于显示的对象类型,控制对象不会在对象树上有任何可视的效果,但是承担各种各样的控制功能。如CaptionObject类型的对象的作用是当鼠标在其范围内拖动时,其所在的对象树会控制关联的容器窗口相应做出移动。
参照HelloBolt3的效果图,接下来还需要在HelloBolt3的对象树模板上加入一个退出按钮,我们来看看这个按钮是如何组成的:这个按钮包括两部分,背景和背景上的文字,那么相应的在对象树模板上加入这两个对象,如下xml节点定义:
<obj id="close.btn.bkg" class="TextureObject">
<obj id="close.btn.msg" class="TextObject">
除了上面两个对象之外,我们还在代表按钮背景的id为"close.btn.bkg" 的对象之上加入了另一个对象,如下xml节点所示:
<obj id="close.btn" class="LayoutObject">
LayoutObject
类型对象同样不会在界面中有任何可见效果,除此之外具备所有UIObject的能力,可以指定位置,加入子对象,接收事件等,一般用于更好的组织对象层次。在此,下方的关闭按钮由若干对象复合组织而成,包括背景和文本,如果视按钮中的各对象组合成为一个逻辑上的整体,那么通过在其上插入LayoutObject来隔离逻辑层次。
纹理对象TextureObject用于展示可拉伸的纹理。纹理(Texture)由两部分组成,一是源位图,一是绘制时拉伸源位图的规则;当绘制纹理时,将源位图上的不同部分按照规则绘制到目标区域。比如常用的九宫纹理,位图的四角不拉伸,上下边缘的中部横向拉伸,左右边缘的中部纵向拉伸,中间部分在两个方向拉伸(纹理资源使用指南)。使用纹理不仅可以方便设计师进行设计和输出易于在交互界面中使用的素材,还能提高Bolt的渲染性能。
TextureObject
对象上的纹理资源在<texture>节点中用资源id标识,纹理作为资源同样需要在资源包中定义。default资源包中bitmap.xml配置了这个纹理,xml节点如下所示:
<texture id="button.normal" type="NineInOne" image="bitmap\btn_login_nor.png" />
其中type属性指定了纹理类型,这里指定为NineInOne即九宫纹理,image属性指定纹理的源位图素材,打开这张位图可以看到,以r=255,g=0,b=255颜色绘制的分隔线将源位图分为九宫,每一部分按照不同方式拉伸到目标大小。
回到MainWnd.xml的TextutreObject对象的定义处,我们看到TextureObject对象的<width><height>分别设置为father.width和father.height.在布局xml中,位置属性可以使用表达式代替绝对值,来灵活的支持对象的自动布局(表达式简介)。表达式中可以使用四则运算符和Bolt内置的关键字,father.width 和 father.height关键字代表父对象的长度和宽度。因为在展示按钮背景的TextureObject对象之上加入了用于分隔的逻辑对象LayoutObject,当上层逻辑对象的大小改变时,即表示按钮大小被改变,此时按钮背景应当有相应改变,前面已经说过子对象的位置本来就是依赖父对象位置的,但是大小需要用表达式来指定,将展示按钮背景的TextureObject对象大小通过表达式与父对象大小绑定,当父对象的大小被改变时,TextureObject对象大小会被自动调整为与父对象的大小相同。此时,父对象的大小为80*30, 那么该TextureObject对象的大小也是80*30.TextureObject展示纹理时,会将纹理拉伸到TextureObject对象大小,那么其上的纹理会被按照九宫纹理的规则将大小为77*24的源位图拉伸到80*30大小绘制。
其中:
MainWnd.xml中:
<!--XML最好存储为UTF-8编码-->
<xlue>
<objtreetemplate id="HelloBolt.Tree" class="ObjectTreeTemplate">
<attr>
<left>-200</left>
<top>-200</top>
<width>2000</width>
<height>2000</height>
</attr>
<obj id="app.bkg" class="ImageObject">
<attr>
<left>0</left>
<top>0</top>
<width>429</width>
<height>267</height>
<!--资源相关的属性使用资源定义xml中设置的资源名-->
<image>app.bkg</image>
<alpha>255</alpha>
</attr>
<children>
<obj id="msg" class="TextObject"> <!--文本对象-->
<attr>
<left>135</left>
<top>100</top>
<width>250</width>
<height>50</height>
<text>Hello,Bolt!</text>
<shadowcolor>system.green</shadowcolor>
<textcolor>system.orange</textcolor>
<font>msg.font</font>
</attr>
</obj>
<!--标题栏,可以模拟App的Titlebar-->
<obj id="title" class="CaptionObject"> <!--带标题的可拖动对象-->
<attr>
<left>0</left>
<top>0</top>
<height>32</height>
<width>father.width</width>
<zorder>100</zorder> <!--对象在z轴的位置,zorder大的排在小的上面-->
</attr>
<children>
<obj id="title.text" class="TextObject">
<attr>
<!-- 使用表达式局中-->
<left>father.width/2-86/2</left>
<top>8</top>
<width>86</width>
<height>24</height>
<text>Hello,Bolt!</text>
<textcolor>system.white</textcolor>
<font>default.font</font>
</attr>
</obj>
</children>
</obj>
<obj id="icon" class="ImageObject"> <!--图像对象-->
<attr>
<left>45</left>
<top>100</top>
<width>60</width>
<height>60</height>
<image>app.icon</image>
<!--设置成拉伸模式,ImageObject默认是不会拉伸其对应的位图的-->
<drawmode>1</drawmode> <!--绘制模式,0为正常,1为拉伸-->
</attr>
</obj>
<obj id="close.btn" class="LayoutObject"> <!--布局对象,根对象-->
<attr>
<left>178</left>
<top>214</top>
<width>80</width>
<height>30</height>
</attr>
<children>
<!--对象树布局中直接定义的对象id即使在不同层次上也不能同名-->
<obj id="close.btn.bkg" class="TextureObject"> <!--纹理对象-->
<attr>
<left>0</left>
<top>0</top>
<width>father.width</width>
<height>father.height</height>
<texture>button.normal</texture> <!--纹理图片资源id-->
</attr>
</obj>
<obj id="close.btn.msg" class="TextObject">
<attr>
<left>0</left>
<top>0</top>
<width>father.width</width>
<height>father.height</height>
<font>default.font</font>
<halign>center</halign> <!--水平对齐方式,缺省值left-->
<valign>center</valign> <!--垂直对齐方式,缺省值top-->
<text>关闭</text>
</attr>
</obj>
</children>
</obj>
</children>
</obj>
</objtreetemplate>
<hostwndtemplate id="HelloBolt.Wnd" class="FrameHostWnd">
<attr>
<mainwnd>1</mainwnd>
<title>Bolt</title>
<layered>1</layered>
<left>200</left>
<top>100</top>
<!--注意这是容器窗口的大小,设置的要合理-->
<width>429</width>
<height>327</height>
<cacheleft>0</cacheleft>
<cachetop>0</cachetop>
<cachewidth>1000</cachewidth>
<cacheheight>720</cacheheight>
<center>1</center>
<topmost>0</topmost>
<visible>1</visible>
<enable>1</enable>
<active>1</active>
<maxbox>0</maxbox>
<minbox>0</minbox>
<minwidth>100</minwidth>
<minheight>72</minheight>
<maxwidth>1000</maxwidth>
<maxheight>720</maxheight>
<appwindow>1</appwindow>
<fps>30</fps>
</attr>
</hostwndtemplate>
</xlue>
color.xml中:
<XLUE>
<resource>
<color id="system.white" red="255" green="255" blue="255" alpha="255" />
<color id="system.black" red="0" green="0" blue="0" alpha="255" />
<color id="system.orange" red="44" green="151" blue="241" alpha="255" />
</resource>
</XLUE>
font.xml中:
<XLUE>
<resource>
<!--下面这个字体的facename最为常用,使用系统的默认字体-->
<font id="default.font" height="14" facename="微软雅黑" />
<font id="msg.font" height="40" facename="微软雅黑" />
<font id="msg.font.bold" height="40" weight="bold" facename="微软雅黑" underline="1"/>
</resource>
</XLUE>
<XLUE>
<resource>
<!--普通的位图资源-->
<bitmap id="app.bkg" path="bitmap\bkg.png" />
<bitmap id="app.icon" path="bitmap\icon.png" />
<!--纹理贴图资源 -->
<!-- 纹理的类型有
:
Stretch,Normal,Tile 拉伸,不拉伸,平铺
NineInOne,ThreeInOneH,ThreeInOneV,FiveInOneH,FiveInOneV, 迅雷传统用的固定区域映射
以及自定义映射
通过定义这些类型,可以方便的让位图按预期意图进行拉伸,同时也方便设计师的工作
-->
<texture id="button.normal" type="NineInOne" image="bitmap\btn_login_nor.png" />
</resource>
</XLUE>