笔记: 用XML创建框架

Posted on 2009-06-21 14:43  apex.Cliz  阅读(1547)  评论(0)    收藏  举报

UI中的常见对象

在用户界面的编写中,最主要用到的是以下三个对象:

Texture

用来在游戏中显示图像、颜色、渐变色。通过XML元素<Texture>实现。

FontString

用来在游戏中显示文本,可以指定特定的字体、大小、颜色,并可以实现诸如下阴影等基本效果。需要XML元素<FontString>。

Frame

即框架,在用户界面中作为各种texture和fontstring的“载体”。Frame是一大类对象,包括很多子类,例如按钮、编辑框、带滚动条的信息框等。Frame之间可以嵌套。需要XML元素<Frame>。

这些对象(在XML代码中则是“元素”)的大小、位置、可见度等都可以通过XML元素的属性等进行自定义。


对象的命名

所有用户界面中的对象都可以通过name属性字段指定一个名字。当然,并不是什么时候都必须指定名字,但名字可以方便在之后的XML或Lua文件中指向这些对象。


指定父对象

除了命名,每个对象还可以有一个父对象。指定父对象有利于定义frame之间的层级关系,有以下好处:

1. 当一个父对象被隐藏,所有其子对象也将自动同时被隐藏。若未指定此关系,则必须在隐藏一个父框架之后,手动隐藏所有附在该框架上的对象,包括按钮、输入框……

2. 框架的有效范围,是通过其父框架有效范围的百分比来指定的,便于缩放。

3. 框架的透明度,是通过其父框架透明度的百分比来指定的,便于在父框架半透明状态时一并使其所有子框架全部进入半透明状态。

大多数暴雪默认框架的父框架是UIParent。UIParent是一个特殊的框架,用来响应特定的指令(Alt+Z)隐藏整个用户界面,并可以实现整个用户界面的缩放功能。在定义用户界面的框架时,应确保其最上级父对象为UIParent,以便使其和其他同属UIParent子对象的框架保持行为一致。

有三种指定父对象的方式,包括:在XML元素的属性字段中指定;直接在XML元素中形成嵌套关系;通过Lua中使用:SetParent()方法指定父对象。

属性字段指定法

可以通过parent属性字段来指定对象间的父子关系。只对frame这种对象有效。

  <Frame name="MyFrame" parent="UIParent">
  </Frame>

XML元素嵌套法

例如,在下面的代码中,根据元素间的嵌套关系,名为MyText的fontstring对象和名为MyGraphic的texture对象都是MyFrame的子对象。

1 <Frame name="MyFrame" parent="UIParent">
2  <Layers>
3   <Layer level="BACKGROUND">
4    <FontString name="MyText" />
5    <Texture name="MyGraphic" />
6   </Layer>
7  </Layers>
8 </Frame>

 

:SetParent()法

任何一个对象一经创建,均可以呼叫:SetParent()方法来指定一个父对象。此父对象作为:SetParent()方法的参数,并必须是一个frame。

例如,可以通过这样的语句指定小地图为MyFrame的父对象:

  MyFrame:SetParent(MiniMap)


在指定父对象的情况下,命名一个对象时,可以加入$parent字串,作为父对象名称的转义符。例如:

  <Frame name="$parentMyFrame" parent="UIParent" />

此框架将被命名为UIParentMyFrame.

此转义符在命名texture和fontstring时也有效。


指定对象大小

所有对象的尺寸通过<Size>元素来指定,可以指定绝对尺寸或相对尺寸。

绝对尺寸

绝对尺寸即是用确切的像素值来指定一个对象的大小。例如,一个宽100像素、高50像素的框架可以这样定义:

  <Frame name="MyFrame">
   <Size x="100" y="50">
  </Frame>

或者用另一种写法:

  <Frame name="MyFrame">
   <Size>
    <AbsDimension x="100" y="50" />
   </Size>
  </Frame>

相对尺寸

使用相对尺寸的对象,必须拥有父对象。所指定的百分比数值,乘以父对象的对应尺寸后,所得的值作为实际的宽/高度数值。

例如:

  <Frame name="MyFrame1">
   <Size x="100" y="50">
  </Frame>

  <Frame name="MyFrame2" parent="MyFrame1">
   <Size>
    <RelDimension x="0.5" y="0.5" />
   </Size>
  </Frame>


对象的锚定

在魔兽世界中,各种对象的定位,均是通过一系列锚点完成的,这些锚点将某框架的一点和另一框架的一点固定在一起。

对一个框架,可用的锚点包括以下九个:

  TOPLEFT  TOP  TOPRIGHT
    ■    ■    ■

LEFT  ■   CENTER  ■    RIGHT

    ■    ■    ■
 BOTTOMLEFT BOTTOM  BOTTOMRIGHT

锚点通过<Anchors>元素进行定义, 包含一个或以上的<Anchor>子元素, 每个子元素包括以下几个属性字段:

point: 当前框架用于固定的锚点
relativePoint: 挂接到的框架上的对应锚点
relativeTo: 挂接到的框架名称

例如, A框架和B框架固定在一起时, 如果在A框架的元素中定义锚点, 则point指的是A上的点, 而relativePoint则是B上的点, relativeTo则应该是B的名称.

此外, <Anchors>元素还可以包含一个<Offset>子元素, 用来描述两锚点间的位移, 用法和<Size>标签类似, 可以描述绝对或相对位移.

例如, 下面的代码建立一个名为MyFrame的新框架,并且将其中心点固定在UIParent父框架的正中心。

  <Frame name="MyFrame" parent="UIParent">
   <Size x="100" y="100" />
   <Anchors>
    <Anchor point="CENTER" relativePoint="CENTER" relativeTo="UIParent">
     <Offset x="0" y="0" />
    </Anchor>
   <Anchors>
  </Frame>

下面的代码再创建一个名为MyFrame2的框架,并将其左顶点和MyFrame的右顶点固定在一起。

  <Frame name="MyFrame" parent="UIParent">
   <Size x="50" y="50" />
   <Anchors>
    <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeTo="MyFrame" />
   <Anchors>
  </Frame>

锚点具有黏着性。如果两框架通过锚点固定在一起,移动其中一个框架时,另一个也会随之移动,并保持锚点固定。


框架和图形元素的层叠问题

在魔兽世界的用户界面中,可以通过定义不同的属性,实现一个框架完全位于另一个框架之上,或者不同的图形元素混合成一层。这些效果是通过三级图形界面实现的,包括:框架层,框架级别,图形层。

框架层/Frame Strata

框架层是框架层叠中最基本的单位。在魔兽世界中,有七级框架层,显示的顺序是从最低级别的框架层到最高级别的框架层,即:最高级别的框架层会位于最前。属于一个框架层中的所有对象,一定会在另一个级别较低的框架层中的任意对象之后得到渲染,同理也一定会在另一个级别较高的框架层中的任一对象之前得到渲染。

七级框架层从最低级到最高级分别是:

BACKGROUND: 通常用于放置不与鼠标事件发生反应的对象。所有位于此框架层中的对象均不会对鼠标事件发生反应,除非其框架级别大于1.
LOW: 被默认用户界面用于增益效果框架、物品耐久度框架、团队界面及宠物框架。
MEDIUM: UIParent框架所在的框架层,也是其所有子框架默认所在的框架层。
HIGH: 被默认用户界面用于按钮、教学框架,以及界面报错、报警信息框架。
DIALOG: 用于任何弹出并试图与用户交互的对话框类框架。
FULLSCREEN: 所有全屏性质的框架(例如默认的世界地图、用户界面选项窗口等)应置于此层
FULLSCREEN_DIALOG: 在FULLSCREEN层之前的对话框用框架层,主要用于对话框、下拉菜单
TOOLTIP: 最高级别的框架层,主要用于鼠标悬停时的提示信息

用下面的代码来指定一个框架所在的层:

  <Frame name="MyFrame" frameStrata="HIGH">
  </Frame>


框架级别/Frame Levels

处于同一框架层中的每一个框架都有自己的框架级别,以此来决定他们显示的先后顺序。框架级别通过frameLevel属性字段来指定;在不指定的情况下,子框架的框架级别默认比其父框架要高,以保证子框架在父框架之前。例如:

  <Frame name="MyFrame" frameStrata="HIGH" frameLevel="5"
  toplevel="true">
  </Frame>

上面的toplevel是一个布尔型的属性字段,指定为true的框架,在受到鼠标点击时,会自动移至该框架层中的最前端。


图形层/Graphical Layers

在之前讲到用XML元素嵌套指定对象间的父子关系时,有这样的代码:

  <Frame name="MyFrame" parent="UIParent">
   <Layers>
    <Layer level="BACKGROUND">
     <FontString name="MyText" />
     <Texture name="MyGraphic" />
    </Layer>
   </Layers>
  </Frame>

在魔兽世界中,所有的图案元素(Texture)和字串元素(FontString)都必须像这样写在<Layers>元素的一个<Layer>子元素里。

和frameStrata类似,layers也可以指定其中每个layer的级别,共有五个,从低级到高级分别是:

BACKGROUND: 位于框架的最底层
BORDER: 所有应该在BACKGROUND前面、其他层后面的对象放在这里
ARTWORK: 所有应处于BACKGROUND及BORDER层之上的非功能性的、装饰性的图形,放在这一层
OVERLAY: 所有功能性的对象,包括按钮、文本标签等,放在这一层
HIGHLIGHT: 仅当鼠标悬停时显示并置于最前端的一层。对应的Layer必须有enableMouse属性字段,并且值为true。

例如, 可以这样创建两个层:

  <Frame name="MyFrame">
   <Layers>
    <Layer level="BACKGROUND">
    </Layer>
    <Layer level="HIGHLIGHT">
    </Layer>
   </Layers>
  </Frame>


常见属性字段

上述的三种基本元素(Frame, Texture及FontString)除了前述的命名、大小、位置等属性字段,还有以下4个常见的属性字段:

Inherits(继承)

魔兽世界中有一套对象的继承系统,允许开发者创建模板,并用其创建新框架。这个属性字段接受用逗号隔开的模板名称列表。有此字段的对象,将自动继承列表中的模板。

Virtual(虚构)

布尔型,其值为true时,此对象在加载时作为模板处理,不产生实际的对象。

setAllPoints

布尔型,其值为true时,此框架将和其父框架拥有相同的大小及位置。

Hidden

布尔值。值为true时,对象创建时处于隐藏状态。


创建图案

图案指的是游戏客户端为客户界面渲染的2D图像,可以是从硬盘中加载的图案文件,alpha值可选的单色色块,或从一种颜色到另一种颜色的渐变图案,全部通过<Texture>标签实现。

除了上面列出的基本元素的常见属性字段外,<Texture>标签还有以下两个属性字段:

file: 需要加载的图案文件所在路径(含文件名)
alphaMode: 指定当需要重叠多层图案时所使用的混合模式,可以是DISABLE, BLEND, ALPHAKEY, ADD或MOD。

创建实色区

用<Color>标签创建一个实色层,包含4个属性字段: r, g, b, a, 分别为红色(red)、绿色(green)、蓝色(blue)及alpha值, 取值范围为0.0~1.0. 使用00~FF色系的,可以按比例转化为小数。

例如,以下的代码将创建一个覆盖整个框架的红色实色层。

  <Frame name="MyFrame">
   <Layers>
    <Layer level="BACKGROUND" setAllPoints="true">
     <Color r="1.0" g="0.1" b="0.1" a="1.0" />
    </Layer>
   </Layers>
  </Frame>

这个层的setAllPoints字段被设为true, 表示它将和它的父框架具有相同的大小和位置, 此处它的父框架正是MyFrame框架本身。


创建渐变色带

渐变色带通过<Gradient>标签创建。<Gradient>标签必须和<Color>标签配合使用,<Color>标签指定一种基本色,<Gradient>标签指定起始色<MinColor>和结束色<MaxColor>,以及渐变的方向(HORIZONTAL / VERTICAL)。实际颜色的各项(r,g,b,a)是通过基本色各项乘以起始色/结束色各项的运算结果。如果要直接用<MinColor>和<MaxColor>标签所指定的颜色进行渐变,可以将基本色指定为白色,即:

  <Color r="1.0" g="1.0" b="1.0" a="1.0" />

例如,一个合法的渐变色块可以这样定义:

 1 <Frame name="GradientTest" parent="UIParent">
 2  <Size x="200" y="100" />
 3  <Layers>
 4   <Layer level="BACKGROUND" setAllPoints=true>
 5    <Texture name="Horizontal">
 6     <Size x="200" y="100" />
 7     <Color r="1.0" g="1.0" b="1.0" a="1.0" />
 8     <Gradient orientation="VERTICAL">
 9      <MinColor r="0.0" g="0.0" b="0.0" a="1.0" />
10      <MaxColor r="1.0" g="1.0" b="0.0" a="1.0" />
11     </Gradient>
12    </Texture>
13   </Layer>
14  </Layers>
15 </Frame>

 


创建图像

只需要在<Texture>标签中用file属性字段指向所需加载的图像文件即可。例如,下面的代码创建了一个100*100的框架并显示暗言术·痛的图标。

 1 <Ui xmlns="http://www.blizzard.com/wow/ui/"
 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3 xsi:schemaLocation="http://www.blizzard.com/wow/ui
 4 ..\FrameXML\UI.xsd">
 5   <Frame name="GraphicTest" parent="UIParent">
 6     <Size x="100" y="100">
 7     <Anchors>
 8       <Anchor point="CENTER" relativePoint="CENTER"
 9        relativeTo="UIParent" />
10     </Anchors>
11     <Layers>
12       <Layer level="BACKGROUND">
13         <Texture name="$parentPainIcon"
14          file="Interface\Icons\Spell_Shadow_ShadowWordPain"
15          setAllPoints="true">
16         </Texture>
17       </Layer>
18     </Layers>
19   </Frame>
20 </Ui>


创建字符串对象

向框架添加文字的过程只需两步,建立一个FontString对象并将它锚点固定到框架上。<FontString>对象也必须置于一个<Layer>元素中。

除了之前所述的属性字段外,<FontString>还有以下几个独有的属性字段:

  font
  
路径,指向一个外部或WoW内部的字体文件,用来显示这段文字。

  bytes
  正数,描述显示文字的字节数上限,超过部分不予显示。

  text
  字符串,将要显示的文字。

  spacing
  正数,单位为像素,指定多行文字间的行距。

  outline
  枚举型,设置字符的外描边,可选以下值: NONE, NORMAL, THICK。

  monochrome
  布尔值,为true时,字符串只以灰度颜色显示。

  nonspacewrap
  布尔值,设定不带空格的长字符串的换行方式。当此值为true时,整个词将换到下一行,否则,字符串将从中间被截断。

  justifyV, justifyH
  设置水平及垂直方向的对齐方式。justifyV可选: TOP, MIDDLE, BOTTOM;justifyH可选: LEFT, CENTER, RIGHT。

  maxLines
  设置可显示的最大行数,超过部分不予显示。


使用模板

通常情况下,开发人员不会每一次都手动指定上面的全部属性,而是会沿用各种现成的模板。例如,下面的代码在屏幕中央生成一行文字,使用GameFontNormalHuge模板:

 1 <Ui xmlns="http://www.blizzard.com/wow/ui/"
 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3 xsi:schemaLocation="http://www.blizzard.com/wow/ui
 4 ..\FrameXML\UI.xsd">
 5   <Frame name="FontTest" parent="UIParent">
 6     <Size x="200" y="50">
 7     <Anchors>
 8       <Anchor point="CENTER" relativePoint="CENTER" />
 9     </Anchors>
10     <Layers>
11       <Layer level="OVERLAY">
12         <FontString setAllPoints="true" justifyV="MIDDLE" justifyH="CENTER" 
13          inherits="GameFontNormalHuge" text="Hello Azeroth!" />
14       </Layer>
15     </Layers>
16   </Frame>
17 </Ui>
 

<FontString>标签还可以包括以下标签来进一步自定义格式:

  <FontHeight>
  带一个val属性字段,或<AbsValue>(绝对) / <RelValue>(相对)子元素,指定该字符串的高度,单位为像素(或相对值)。

  <Color>
  改变字符串的颜色。格式同之前的<Color>标签,指定r,g,b,a四项数值。

  <Shadow>
  添加下阴影效果,带<Color>及<Offset>子元素指定颜色及阴影距离。


对象的可见与否

在魔兽世界中,任何一个对象最终真正地显示在屏幕上,都必须满足以下条件:

  ·此对象必须有可见的部分,例如文字、图像、背景颜色、边框等。不包含这些成员的对象是不可见的,空的图案或字串对象实际上也是不可见的。
  ·此对象必须拥有正的宽度和高度。
  ·此对象位置必须处在屏幕可显示范围之内。
  ·此对象,及其父对象和父对象的所有前代对象均不能被隐藏。

隐藏一个对象可用的方法包括直接在XML元素中将hidden属性字段设为true,或者在Lua脚本中呼叫:Hide()方法。

可以通过:IsShown()方法检查一个对象是否被隐藏;如果它可见,此方法返回1。还可以用:IsVisible()方法检查一个对象,及其父对象和父对象的所有前代对象是否都被正确显示。