17.下拉列表框UIComboBox类
下拉列表框事实上就是一个文本框(目前还没有实现文本框,我认为编写文本框的难度应该是最大的,等以后必须用到时在攻克它吧,本例中的文本框是用一个带背景的文字代替的)、文本框右侧的复选按钮和列表框组合而成的控件,它要实现的主要功能如下:
- 绘制文本框背景和其中的文字,当选中列表框一个文字项后需要改变显示的文字;
- 绘制文本框右侧的复选按钮,当点击它时会显示向下的箭头并显示列表框,再次点击变为向上箭头并隐藏列表框。
具体代码代码如下:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using StunEngine.Controllers;
using StunEngine.SceneManagement;
namespace StunEngine.SceneNodes.UI
{
///
/// 下列列表框
///
public class UIComboBox :UISceneNode
{
//默认值
private static readonly float DefaultComboBoxWidth = 160.0f;
private static readonly float DefaultScrollBarWidth = 16.0f;
private static readonly float DefaultListBoxHeight = 92.0f;
private static readonly Rectangle DefaultTextBoxRect = new Rectangle(1, 1, 6, 6);
private static readonly Rectangle DefaultButtonRectOrigin = new Rectangle(0, 16, 16, 16);
private static readonly Rectangle DefaultButtonRectHighlight = new Rectangle(16, 16, 16, 16);
private static readonly Rectangle DefaultButtonRectChecked = new Rectangle(0, 48, 16, 16);
private static readonly Rectangle DefaultButtonRectCheckedHighlight = new Rectangle(16, 48, 16, 16);
///
/// 下拉列表框右侧的复选框控件
///
UICheckBox button;
///
/// 列表框控件
///
UIListBox listbox;
///
/// 列表框高度,默认为92。它的宽度无需指定,等于下拉列表框宽度,默认为160。
///
private float listBoxHeight;
///
/// 滚动条宽度,默认为16。
///
float scrollBarWidth;
///
/// 下拉列表框的宽度,默认为160。
///
float width;
///
/// 文本框中的文字。
///
private string text;
///
/// 文字使用的字体。
///
private SpriteFont font;
///
/// 文本使用的颜色
///
private Color textColor;
///
/// 文本框背景图像矩形
///
private Rectangle textBoxRect;
///
/// 按钮普通状态图像矩形
///
private Rectangle buttonRectOrigin;
///
/// 按钮高亮状态图像矩形
///
private Rectangle buttonRectHighlight;
///
/// 按钮选中状态图像矩形
///
private Rectangle buttonRectChecked;
///
/// 按钮选中时高亮状态图像矩形
///
private Rectangle buttonRectCheckedHighlight;
///
/// 当选中的文字项发生改变时引发的事件。
///
public event EventHandler SelectionChanged = null;
///
/// 列表框是否处于打开状态。
///
bool justOpened = false;
///
/// 创建一个默认ComboBox,文字项数组为空。
///
/// 引擎
/// 所属场景
public UIComboBox(StunXnaGE engine, Scene setScene):this(engine ,setScene ,null)
{
}
///
/// 创建一个ComboBox,需要传递文字项数组
///
/// 引擎
/// 所属场景
/// 文字项数组
public UIComboBox(StunXnaGE engine, Scene setScene,string [] setItems)
: this(engine, setScene, Vector2.Zero, "Textures/UI/UITextBox", DefaultComboBoxWidth,DefaultListBoxHeight ,DefaultScrollBarWidth,engine.DefaultFont, Color.White,DefaultTextBoxRect ,DefaultButtonRectOrigin ,DefaultButtonRectHighlight ,DefaultButtonRectChecked ,DefaultButtonRectCheckedHighlight ,setItems)
{
}
///
/// 创建一个UIComboBox,内部方法,只能在引擎内部调用。
///
/// 引擎
/// 所属场景
/// 控件的2D屏幕位置
/// 纹理名称
/// 下拉列表框宽度
/// 列表框高度
/// 滚动条宽度
/// 文字使用的字体
/// 文字颜色
/// 文本框图像矩形
/// 按钮普通状态图像矩形
/// 按钮高亮状态图像矩形
/// 按钮选中状态图像矩形
/// 按钮选中时高亮状态图像矩形
/// 文字项数组
internal UIComboBox(StunXnaGE engine, Scene setScene, Vector2 setPosition,string setTextureName,float setWidth,float setListBoxHeight,float setScrollBarWidth,SpriteFont setFont,Color setTextColor,Rectangle setTextBoxRect,Rectangle setButtonRectOrigin,Rectangle setButtonHighlight,Rectangle setButtonRectChecked,Rectangle setButtonRectCheckedHighlight,string [] setItems) : base(engine, setScene, setPosition, setTextureName)
{
this.font =setFont ;
this.textColor = setTextColor;
this.width = setWidth;
this.scrollBarWidth = setScrollBarWidth;
this.listBoxHeight = setListBoxHeight;
this.size=new Vector2 (width ,font .LineSpacing );
this.textBoxRect =setTextBoxRect ;
this.buttonRectOrigin = setButtonRectOrigin;
this.buttonRectHighlight = setButtonHighlight;
this.buttonRectChecked = setButtonRectChecked;
this.buttonRectCheckedHighlight = setButtonRectCheckedHighlight;
//初始化并添加一个下拉按钮,实际上是一个不含文字的复选框
button = new UICheckBox(engine, setScene, new Vector2(position.X + size.X - size.Y, position.Y), "Textures/UI/UIScrollBar", new Vector2(size.Y, size.Y), null, engine.DefaultFont, Color.White, Color.White, buttonRectOrigin, buttonRectHighlight, buttonRectChecked, buttonRectCheckedHighlight);
button.TabStop = false;
button.CheckedChanged +=new EventHandler(button_CheckedChanged);
this.scene.AddNode(button);
//初始化并添加一个列表框
if(setItems !=null)
listbox = new UIListBox(engine ,setScene,setItems);
else
listbox = new UIListBox(engine, setScene);
listbox.ChangeSelection +=new EventHandler(listbox_ChangeSelection);
listbox .MouseClick +=new System.Windows.Forms.MouseEventHandler(listbox_MouseClick);
listbox.TabStop = false;
this.scene.AddNode(listbox);
//鼠标点击下拉列表框时控制列表框的可见与否,其实就是调用按钮的点击事件
this.MouseClick += new System.Windows.Forms.MouseEventHandler(combo_MouseClick);
//绘制下拉列表框
Redraw();
}
#region 属性
///
/// 获取或设置文本框中的文字
///
public string Text
{
get { return text; }
}
///
/// 获取或设置文本使用的字体
///
public SpriteFont Font
{
get { return font; }
set
{
font = value;
listbox.Font = value;
}
}
///
/// 获取或设置文本使用的颜色
///
public Color TextColor
{
get { return textColor; }
set { textColor = value; }
}
///
/// 获取或设置文本框背景图像矩形
///
public Rectangle TextBoxRect
{
get { return textBoxRect; }
set { textBoxRect = value; }
}
///
/// 获取或设置按钮普通状态图像矩形
///
public Rectangle ButtonRectOrigin
{
get { return buttonRectOrigin; }
set { buttonRectOrigin = value; }
}
///
/// 获取或设置按钮高亮状态图像矩形
///
public Rectangle ButtonRectHighlight
{
get { return buttonRectHighlight; }
set { buttonRectHighlight = value; }
}
///
/// 获取或设置按钮选中状态图像矩形
///
public Rectangle ButtonRectChecked
{
get { return buttonRectChecked; }
set { buttonRectChecked = value; }
}
///
/// 获取或设置按钮选中时高亮状态图像矩形
///
public Rectangle ButtonRectCheckedHighlight
{
get { return buttonRectCheckedHighlight; }
set { buttonRectCheckedHighlight = value; }
}
///
/// 获取或设置滚动条宽度,默认为16。
///
public float ScrollBarWidth
{
get { return listbox.ScrollBarWidth;}
set { listbox.ScrollBarWidth = value; }
}
///
/// 获取或设置选中文字项的文字
///
public string SelectedItem
{
get
{
return listbox.SelectedItem;
}
set
{
listbox.SelectedItem = value;
text = listbox.SelectedItem;
}
}
///
/// 获取选中的文字项的索引
///
public int SelectedIndex
{
get { return listbox.SelectedIndex; }
set
{
listbox.SelectedIndex = value;
text = listbox[value];
}
}
///
/// 获取或设置列表框的文字项数组
///
public List Items { get { return listbox.Items; } set { listbox.Items = value; } }
///
/// 获取列表框是否被显示
///
public bool Opened { get { return listbox.IsVisible; } }
#endregion
#region 事件相关方法
///
/// 在文字项数组中添加一个数据项
///
public void AddItem(string item)
{
listbox.AddItem(item);
if (!justOpened)
listbox.IsVisible = false;
}
///
/// 下列列表框位置改变时需要重新绘制。
///
protected override void OnLocationChanged()
{
Redraw();
base.OnLocationChanged();
}
///
/// 下列列表框大小改变时需要重新绘制。
///
protected override void OnSizeChanged()
{
Redraw();
base.OnSizeChanged();
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
button.IsVisible = isVisible;
if(justOpened )
listbox.IsVisible =isVisible ;
}
///
/// 重新绘制下列列表框。
///
private void Redraw()
{
this.size = new Vector2(size.X, font.LineSpacing);
button.Position = new Vector2(position.X + size.X - size.Y, position.Y);
listbox.Size = new Vector2(width, listBoxHeight);
listbox.ScrollBarWidth = scrollBarWidth;
listbox.Position = new Vector2(position.X, position.Y + size.Y);
listbox.Font = font;
listbox.Size = new Vector2(size.X, listbox .Size .Y);
if (!justOpened)
listbox.IsVisible = false;
}
///
/// 点击列表框关闭列表框
///
///
///
void listbox_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
{
listbox.IsVisible = false;
}
///
/// 将文本框中的文字设置为选中的文字项,如果选中的文字项发生变化则引发SelectionChanged事件。
///
///
///
void listbox_ChangeSelection(object sender, EventArgs e)
{
string previousItem = text;
text = listbox.SelectedItem;
if (text != previousItem && SelectionChanged != null)
SelectionChanged(listbox.SelectedItem, null);
Close();
}
///
/// 点击控件相当于点击右侧按钮
///
///
///
void combo_MouseClick(object sender, EventArgs e)
{
button.OnCheckedChanged(e);
}
///
/// 点击按钮打开列表框
///
///
///
void button_CheckedChanged(object sender, EventArgs e)
{
if (isVisible)
{
if (!listbox.IsVisible)
Open();
else
Close();
}
}
///
/// 打开列表框
///
private void Open()
{
justOpened = true;
listbox.IsVisible = true;
}
///
/// 关闭列表框
///
private void Close()
{
listbox.IsVisible = false;
justOpened = false;
}
#endregion
///
/// 绘制控件
///
public override void Draw(GameTime gameTime, bool useReflection)
{
//获取图像淡入淡出的透明颜色
alphaTextureColor = new Color(color, scene.TransitionAlpha);
//绘制文本框背景
StunXnaGE.SpriteBatch.Draw(material.Textures[0], new Rectangle((int)position.X, (int)(position.Y), (int)(size.X - size.Y), (int)size.Y), textBoxRect, alphaTextureColor, rotation, origin, spriteEffect, layerDepth);
//绘制文本框上的文字
if (text != null)
StunXnaGE.SpriteBatch.DrawString(font, text, position, textColor);
}
#region 单元测试
#if DEBUG
///
/// 测试UIComboBox类
///
public static void TestUIComboBox()
{
UIComboBox comboBox = null;
TestGame.Start("测试UIComboBox类,可按空格,上下键,数字键12",
delegate
{
comboBox = new UIComboBox(TestGame.engine, TestGame.scene);
TestGame.scene.AddNode(comboBox);
comboBox.AddItem("1");
comboBox.AddItem("2");
comboBox.AddItem("3");
comboBox.AddItem("4");
comboBox.AddItem("5");
comboBox.AddItem("6");
comboBox.Position = new Vector2(100, 150);
comboBox.SelectedIndex =3;
//关闭相机控制器
TestGame.scene.fpsCamCtrl.Enabled = false;
},
delegate
{
//按向下键移动控件
if (Input.KeyboardDownJustPressed)
comboBox.Position += new Vector2(5, 5);
//按向上键改变大小
if (Input.KeyboardUpJustPressed)
comboBox.Size += new Vector2(5, 5);
//按空格键测试isVisible属性
if (Input.KeyboardSpaceJustPressed)
comboBox.IsVisible = !comboBox.IsVisible;
//按数字1键新添数据项
if (Input.KeyboardKeyJustPressed(Keys.D1))
comboBox.AddItem("NewItem");
//按数字2键改变滚动条宽度
if (Input.KeyboardKeyJustPressed(Keys.D2))
comboBox.ScrollBarWidth += 2;
});
}
#endif
#endregion
}
}
代码有点长,其实关键代码并不多,只是为了使用灵活,这个控件(其实前面的控件也是)提供了很多可以被用户改变的属性,希望看代码时别被这些东西所干扰。
单元测试截图如下:

现在的UI类图如下:

2D编程终于告一段落了,其实我更感兴趣的是3D,会在下一个教程开始展开。
发布时间:2010/2/25 下午12:58:42 阅读次数:8417
