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 ListItems { 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 阅读次数:7675