Qt中的Layout实现了窗口控件的自动布局,使得开发者不需要考虑不同尺寸窗口,而轻松布局窗口控件。下面在Qt源代码基础上,以MFC中的控件体会其思想。
一、原理
Layout的核心数据结构是窗口和窗口上的控件链表,以及向链表中添加控件这一方法。
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
class CBox;
2![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
3
class CzLayout
4![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
5![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
6![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
7
public:
8![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
9
void AddThings(CWnd* pThing,
10![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
11
int fromRow, int fromCol, int spanRow, int spanCol);
12![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
13
private:
14![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
15
CWnd* m_pOwner;
16![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
17
std::list<CBox*> m_things;
18![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
19
};
20![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
对应用环境的要求是,需要进行自动布局的控件必须继承自同一个父类,以及一个获取窗口大小尺寸的接口函数。比如在MFC中,所有控件都派生自CWnd这个类,而为每个窗口都提供了一个GetWindowRect这个函数来获取被布局的窗口尺寸。
AddThings方法简单说明:
一共五个参数:控件指针,起始位置(行/列)以及大小(占spanRow行/spanCol列)。
该方法负责向控件链表中添加控件,并实时更新所有控件在窗口中的位置。
CBox包装了控件,提供控件在Layout中的起始位置以及大小信息。
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
2
class CBox
3![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
5![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
6
private:
7![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
8
CWnd* m_item; //控件指针
9![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
10
int m_Row, m_Col; //起始位置
11![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
12
int m_spanRow, m_spanCol; //大小
13![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
14
};
15![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
二、用法
在窗口初始化的时候,创建Layout,并向Layout中添加控件。
m_pLayout->AddThings(&m_StaticCtrls[0] , 0, 0, 1, 1);//在拥有m_pLayout的窗口上添加控件m_StaticCtrls[0],开始位置是第(0,0)位置,所占宫格大小是1行,1列。(Layout中只有类似“宫格”这样的概念,这里的起始位置是在第几宫格开始/大小是占多少宫格的意思。)
此时窗口的布局大致如下:(只有1×1宫格,窗口区域和m_StaticCtrls[0]区域重叠)
![](http://www.cppblog.com/images/cppblog_com/wealth/1.GIF)
m_pLayout->AddThings(&m_StaticCtrls[2], 0, 2, 2, 1);//在第(0,2)位置开始的(2,1)宫格放置控件m_StaticCtrls[2]。
![](http://www.cppblog.com/images/cppblog_com/wealth/6.GIF)
此时窗口被分为2×3的宫格,其中(0,0,1,1)位置(黄色位置)是m_StaticCtrls[0],(0,2,2,1)位置(天蓝色位置)是m_StaticCtrls[2]。
三、其他细节控制
控件尺寸显示策略。这些策略需要不同的控件自己来考虑。
四、源代码
/Files/Wealth/Layout.7z