4.2. Hello GUI 布局篇(1)
(配套光盘中提供本节教程的动画版)
GUI编程中的“布局/Layout”,是指用户界面中,各个子控件(如按钮,列表框等)如何在其父窗口中保持定位。最简单的定位方法是采用X,Y坐标。即,程序记录控件的左上角坐标,再记录控件的大小(长与宽)。这种方法可以称作“绝对定位法”。
无论是C++,还是其它语言的GUI库,只要支持跨平台,则其最主要的布局方法,都不约而同的采用了另外一种方法——“相对定位法”——比如采用“百分比”来定位。
试举一例:假设一个对话框只有两个按钮在同一水平线摆着,绝对定位法规定了左右两个按钮的XY坐标及长宽;而相对定位法则规定两个按钮各占50%的宽度——这是一个很典型的区别,但不是全部。
wxWidgets中,用于实现相对定位的控件,被称为“Sizer”类。通过“Hello GUI 布局篇(1)(2)”两小节,我们将在Code::Blocks中完成一个相比“Hello GUI 基础篇”要复杂一些的界面设计。
在“布局篇(1)”中,我们的学习任务是:熟悉Code::Blocks内置的界面可视化设计工具wxSmith的使用。了解wxBoxSizer的基本用法。
4.2.1. wxSmith基础
首先,请与《Hello GUI 基础篇》小节相同的方法,通过“wxWidgets 项目生成几层”,新建一个wxWidgets项目,命名为“HelloGUILayout”。向导将自动进入wxSmith提供的可视化设计界面。下面介绍该界面所包含的多个子面板。
- 设计期窗口
居中显示的是默认产生的“Hello wxWidgets”对话框在设计阶段时的界面:
图 68 设计期窗口
在这个界面上,我们可以选择、删除、拖动,或插入新的控件。
- 控件面板
底部是一个多页子窗口,每一页都排列着的多个表示控件的图标,这就是控件面板。我们可以从上面选择一个控件,然后将它加入到设计期窗口中。
图 69 控件面板
- 控件树面板
在整个Code::Blocks的左侧边栏(默认状态下),显示的是“控件树面板”。内容是以“树”形结构列出已经被加入设计期窗口中的每个控件(包括窗口自身)。树的父子节点关系,对应控件的包含关系。
根节点之下的“HelloGUILayout”表示当前项目文件。再下一层,wxSimth首先将窗口按类型划分为“wxDialog/对话框”或“wxPanel/面板”或其它,在本项目中,仅存在对话框,所以此时,第三层节点上,只显示一个“wxDialog”。
“wxDialog” 之下是“HelloGUILayoutDialog”,它表示一个同名的资源文件。一个资源文件内可以包含多个对话框,但通常只有一个,本例也是如此,所 以在“HelloGUILayoutDialog”之下只有一个“wxDialog”,在节点树中,它才是表示前述的设计期窗口。
图 70 控件树面板
如图所示,控件树列表位于“资源文件”页内,而通常后者又和“项目”及“符号”以分页的方式,位于同一个窗口中。
当们在树中选中一个节点时,设计期窗口中对应的控件将被同步选中,反之亦然。
〖课堂作业〗:熟悉控件树
请通过点击控件树的不同节点,并观察设计期窗口中选中控件变化过程,熟悉控件对与设计期窗口控件的对应关系。
- 控件属性面板
在控件树面板下是控件属性面板,此处显示设计期窗口中,当前选中控件的属性,我们可以观察或修改属性。下图是选中About按钮时,所显示的属性。
图 71 控件属性面板
控件属性面板的最顶部还有两个图形小按钮。其中长得像一对大花括号{}的按钮,用于切换到“事件页”,可用以设置控件的事件。
- 快速操作工具栏
在设计期窗口的左侧,有一栏竖着的工具栏。称之为“快速操作工具栏”。
前四个图标,用于切换,当从“控件面板”中选中一个控件时,以何种方式插入到“设计期窗口”:
![]() | 选中本图标,则在控件面板点击一个控件之后,必须移动鼠标到目标位置点击,才会将控件添加到设计期窗口中。 这是一种很直观的操作方式,但在复杂情况下,鼠标反倒无法直观的表示所要添加的位置。则需要采用后面的方式。 |
![]() | 选中本图标,则在控件面板点击一个控件之后,如果当前设计期窗口选中的是一个Sizer,或者一个父窗口,则所选控件将自动添加入所选Sizer或父窗口中;否则,等同前一图标。 |
![]() | 选中本图标,则在控件面板选择一个控件之后,将自动加入到设计期窗口中当前选中控件的之前。 |
![]() | 选中本图标,则在控件面板选择一个控件之后,将自动加入到设计期窗口中当前选中控件的之后。 |
表格 4 控件插入位置切换
其余三个工具图标含义是:
![]() | 删除当前选中控件。 |
![]() | 预览设计效果。(只预览控件属性,事件不起作用)。 |
![]() | 切换是否显示“控件定位面板”。 |
表格 5 快速操作其它工具图标含义
- 控件定位面板
请保持“About”按钮处于选中状态,然后点击前述最后一个工具图标,显示出“定位属性快速操作”面板,如下图:
图 72 快速操作工具栏
Border/ 边界:设置当前控件四周的空白。如果有A,B两个相邻控件,并且他们的Border都设置为4,则A,B控件之间,至少相隔8个点。除了可以设置空白大小 之外,左侧的四个复选框,用于设置上、下、左、右是否需要空白。“Dialog Units”则表示空白大小是否采用“对话框单位”(通常不采用)。
Placement/位置:九个单选框,可以设置选中控件的对齐位置,比如左上,右下,居中等。“定形(Shaped)”:用于确定控件是否采用固定的长宽比例。“扩展(Expand)”:用于确定控件是否在纵向(或横向)上自动伸缩。
Proportion/ 比例:如果为0,则表示控件的长度(或者宽度)大小固定。否则,表示它所占用的比例值。例如有3个按钮并排摆置,它们的Proportion值分别 为:0、1、2。则第一个按钮长度固定,第二、三个按钮长度分别占用剩余空间的1/3和2/3,如下图所示:
图 73 Proportion属性示例
Button2 的Proportion值为1,Button3的Proportion值为2,二者相加,得到比例值的分母:“3”。假设在运行期,用户拉长窗口宽度,根 据上图不难推断:Button1的大小保持不变,而Button2、和Button3的宽度将增加,并且二者宽度比例一值保持为:“1:2”。实际效果如 下图所示:
图 74 总长度增加,Button2、3宽度增加,但二者比例不变
上图中,读者可能也发现了,三个Button之间,存在固定间隔,那正是“Border”所起的作用。
〖重要〗: Border、Placement、Proportion都只是附加属性
性 别、身高、体重……这些可算得上一个人的“原生属性”;而当你坐在电影院里,你会临时多出一个附加属性:座号。可以认为,座号是你在电影院里用来“定位” 的一个附加属性。“Border、Placement、Proportion”这些属性和一个控件关系与此类似:纯粹的控件并不具备这些属性,仅当要把控 件摆置在一个Sizer内时,才会临时增加这些附加属性。
“控件定位面板”是一个方便我们快速找到和定位有关的附加属性。这些属性我们一样可以在“控件属性面板”中找到。在后面行文时,当涉及需要修改控件属性,为了统一,可能只提到在“控件属性面板”中查找,但这可不能成为你不去使用“控件定位面板”的借口。
4.2.2. wxBoxSizer基础
wxWidgets 提供了数个不同的Sizer类,不过最常用的是wxBoxSizer。wxBoxSizer有一个重要的属性叫“Orientation/方向”。当它的 值为“wxHORIZONTAL”时,其内的子控件将横向排列,如果值为“wxVERTICAL”,则子控件纵向排列。
〖课堂作业〗:熟悉wxBoxSizer的“Orientation”属性
请在本例的“设计期窗口”中,选中一个wxBoxSizer,然后在“控件属性面板”中,找到其“Orientation”属性,并观察其属性值。
认识了wxBoxSizer,让我们重新观察当前的设计期窗口的组成。
图 75 设计期窗口的组成
无论直接观察当前的设计期窗口,还是从“控件树面板”中检查节点关系,现在我们可以发现,窗口中存两个wxBoxSizer。外围是一个横向的Sizer,内部右边是一个纵向的Sizer。二者内部子控件的排列情况,在上图中有相当清楚的标注。
稍事休息,请马上进入布局篇(2)。
白话C++