2.Border Layout 自定义一个Layout来完成布局。
目标:

1.添加控件的函数 void QLayout::addWidget ( QWidget * w )
在这个例子里面我们重载这个函数 void addWidget ( QWidget * w, int position)
2.添加到布局里面的都是QLayoutItem。我们把QLayoutItem和position封装成一个结构体ItemWrapper。
QList <ItemWrapper *> list。 私有变量list来管理布局中控件数量。
阅读官方文档:
To make your own layout manager, implement the functions addItem(), sizeHint(), setGeometry(), itemAt() and takeAt(). You should also implement minimumSize() to ensure your layout isn't resized to zero size if there is too little space. To support children whose heights depend on their widths, implement hasHeightForWidth() and heightForWidth().
1.先考虑布局的尺寸问题(布局的长度和宽度问题)
QSize BorderLayout::sizeHint() const 返回布局的理想的长度和宽度。
QSize BorderLayout::minimumSize() const 空间不够时,布局所需的最小的长度和宽度(布局不能少于这个最小的长度和宽度)
我们设计一个 QSize BorderLayout::calculateSize(SizeType sizeType) const函数来计算
enum SizeType { MinimumSize, SizeHint }
QSize BorderLayout::sizeHint() const { return calculateSize(SizeHint ); }
QSize BorderLayout::minimumSize() const { return calculateSize(MinimumSize); }
calculateSize函数中,我们遍历布局中的每个控件,计算出理想尺寸和最小尺寸
QSize BorderLayout::calculateSize(SizeType sizeType) const
{
QSize totalSize; for(int i=; i<list.size(); i++) {
ItemWrapper *wrapper = list.at(i);
QLayoutItem *item = wrapper->item;
Position position = wrapper->position;
QSize itemSize; if(sizeType == MinimumSize)
itemSize = item->minimumSize();
else
itemSize = item->sizeHint(); if(position == North || position == South || position == Central) {
totalSize.rheight() += itemSize.rheight();
} if(position == West || position == East || position == Central) {
totalSize.rwidth() += itemSize.rwidth();
}
} return totalSize;
}
2.添加控件的方法,添加控件也就是把控件添加到list中去
void QLayout::addItem ( QLayoutItem * item ) [pure virtual] 这个函数在应用程序中程序员不调用。
void addWidget ( QWidget * w, Position position) 最常用的添加控件方法。我们这里重载该函数,添加一个参数 position
void add(QLayoutItem *item, Position position) 我们实现add函数来添加控件
void BorderLayout::addItem(QLayoutItem *i)
{
add(i, West);
} void BorderLayout::addWidget(QWidget *w, Position position)
{
add(new QWidgetItem (w), position);
} void BorderLayout::add(QLayoutItem *i, Position position)
{
list.append(new ItemWrapper(i, position));
}
3.查找和删除控件的方法
QLayoutItem * itemAt(int index) const; 返回索引下的QLayoutItem
QLayoutItem * takeAt(int index); 删除索引下的QLayoutItem 并返回QLayoutItem的值
QLayoutItem * BorderLayout::itemAt(int index) const
{
ItemWrapper *wrapper = list.value(index);
if(wrapper)
return wrapper->item;
else
return ;
} QLayoutItem * BorderLayout::takeAt(int index)
{
if(index >= && index < list.size()) {
ItemWrapper *wrapper = list.takeAt(index);
return wrapper->item;
}
return ;
}
list中takeat函数删除索引是index的值
4.布局中控件的数量,布局的高度是否依赖其宽度,布局的延伸方向。
Qt::Orientations expandingDirections() const;
bool hasHeightForWidth() const;
int count() const;
Qt::Orientations BorderLayout::expandingDirections() const
{
return Qt::Horizontal | Qt::Vertical;
} bool BorderLayout::hasHeightForWidth() const
{
return false;
} int BorderLayout::count() const
{
return list.size();
}
5。我们现在知道有多少控件,每个控件的尺寸,整个布局的尺寸。
但是控件摆放在整个布局中那个位置,如何摆放。这里需要void setGeometry(const QRect &rect)函数。
QLayout::setGeometry(rect). 获得布局的整个矩形大小。
然后设施每个QLayoutItem的setGeometry函数。把每个控件放在指定的位置
void BorderLayout::setGeometry(const QRect &rect)
{
ItemWrapper *center = ; int northHeight = ;
int southHeight = ;
int centerHeight = ;
int westWidth = ;
int eastWidth = ; int i = ; QLayout::setGeometry(rect); for(i = ; i < list.size(); i++) {
ItemWrapper *wrapper = list.at(i);
QLayoutItem *item = wrapper->item;
Position position = wrapper->position; if(position == North) {
item->setGeometry(QRect(rect.x(), northHeight, rect.width(), item->sizeHint().height()));
northHeight += item->geometry().height() + spacing();
}
else if(position == South) {
item->setGeometry(QRect(item->geometry().x(), item->geometry().y(), rect.width(),
item->sizeHint().height()));
southHeight += item->geometry().height() + spacing(); item->setGeometry(QRect(rect.x(), rect.y()+rect.height()-southHeight+spacing(),
item->geometry().width(), item->geometry().height()));
}
else if(position == Central)
center = wrapper;
} centerHeight = rect.height() - northHeight - southHeight; for(i = ; i < list.size(); i++) {
ItemWrapper *wrapper = list.value(i);
QLayoutItem *item = wrapper->item;
Position position = wrapper->position; if(position == West) {
item->setGeometry(QRect(westWidth, northHeight, item->sizeHint().width(), centerHeight));
westWidth += item->geometry().width() + spacing();
}
else if(position == East) {
item->setGeometry(QRect(item->geometry().x(), item->geometry().y(),
item->sizeHint().width(), centerHeight)); eastWidth += item->geometry().width() + spacing(); item->setGeometry(QRect(rect.width() - eastWidth + spacing(), northHeight,
item->geometry().width(), item->geometry().height()));
}
} if(center) {
center->item->setGeometry(QRect(westWidth, northHeight,
rect.width() - westWidth - eastWidth, centerHeight));
} }
效果图:

源代码: https://github.com/Satius/qt5/tree/master/qtbase/examples/widgets/layouts/borderlayout
2.Border Layout 自定义一个Layout来完成布局。的更多相关文章
- 自定义View(7)官方教程:自定义View(含onMeasure),自定义一个Layout(混合组件),重写一个现有组件
Custom Components In this document The Basic Approach Fully Customized Components Compound Controls ...
- 自定义View Layout过程 (3)
目录 目录 1. 知识基础 具体请看我写的另外一篇文章:(1)自定义View基础 - 最易懂的自定义View原理系列 2. 作用 计算View视图的位置. 即计算View的四个顶点位置:Left.To ...
- Customize the View Items Layout 自定义视图项目布局
In this lesson, you will learn how to customize the default editor layout in a Detail View. For this ...
- 自定义一个更好用的SwipeRefreshLayout(弹力拉伸效果详解)(转载)
转自: 自定义一个更好用的SwipeRefreshLayout(弹力拉伸效果详解) 前言 熟悉SwipeRefreshLayout的同学一定知道,SwipeRefreshLayout是android里 ...
- 在Dynamics CRM中自定义一个通用的查看编辑注释页面
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复162或者20151016可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 注释在CRM中的显示是比较特别, ...
- [WPF 自定义控件]自定义一个“传统”的 Validation.ErrorTemplate
1. 什么是Validaion.ErrorTemplate 数据绑定模型允许您将与您Binding的对象相关联ValidationRules. 如果用户输入的值无效,你可能希望在应用程序 用户界面 ( ...
- Android The layout "activity_main" in layout has no declaration in the base layout folder
报错: The layout "activity_main" in layout has no declaration in the base layout folder; thi ...
- SpringMVC 自定义一个拦截器
自定义一个拦截器方法,实现HandlerInterceptor方法 public class FirstInterceptor implements HandlerInterceptor{ /** * ...
- jQuery Validate 表单验证插件----自定义一个验证方法
一.下载依赖包 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW 访问密码 f224 二.引入依赖包 <script src="../../scripts/j ...
随机推荐
- Java 开发手册之编程规约
一.编程规约 (一) 命名规约 1.[强制] 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束.(代码规范,易读) 反例: name / __name / $Object / n ...
- JQuery 提示用户名密码不为空
$(document).ready(function(){ //HTML()替换 HTML函数 //append()追加 :input = :t ...
- iTunes文件共享
在Info.plist文件中添加UIFileSharingEnabled键,并将键值设置为YES.将您希望共享的文件放在应用程序的Documents目录.
- C# 通过窗口句柄获取程序路径 图标
转自:http://qqhack8.blog.163.com/blog/static/11414798520113363829505/ C# 通过窗口句柄获取程序路径 图标using System;u ...
- ACM学习历程—SNNUOJ 1239 Counting Star Time(树状数组 && 动态规划 && 数论)
http://219.244.176.199/JudgeOnline/problem.php?id=1239 这是这次陕西省赛的G题,题目大意是一个n*n的点阵,点坐标从(1, 1)到(n, n),每 ...
- Servlet和JSP规范与Tomcat版本对应关系
apache tomcat 官网地址:http://tomcat.apache.org/whichversion.html
- fn project 扩展
目前支持的扩展方式 Listeners - listen to API events such as a route getting updated and react accordingly. ...
- fragment在水平/垂直时的应用
直接看代码 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedIns ...
- laravel 中config的使用
在laravel的config中添加配置文件(比如:alipay.php)文件内容为return数组的形式 在方法中使用config()函数获取数据 $config = config('alipay. ...
- shell 正则表达式与文件名匹配
1) . : 匹配任意单ASCII 字符,可以为字母,或为数字. 2) 举例: ..XC..匹配deXC1t.23XCdf 等,.w..w..w.匹配rwxrw-rw- 行首以^匹配字符串或字符序列 ...