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 ...
随机推荐
- JDBC 1 利用Statement对数据库进行增删改查
准备工作 1新建po类:User private int id; private String name; private String pwd; set,get方法省略 2 新建UserDao类, ...
- 一起来看CORE源码(一) ConcurrentDictionary
先贴源码地址 https://github.com/dotnet/corefx/blob/master/src/System.Collections.Concurrent/src/System/Col ...
- VS 生成 dll、exe 版本号与SVN版本号一致
1.VS 可自动生成版本号 注释掉以下两行代码 [assembly: AssemblyVersion("1.0.0.0")][assembly: AssemblyFileVersi ...
- UART驱动分析
在linux用户层上要操作底层串口需要对/dev/ttySxxx操作,这里的ttySx指实际的终端串口. 以下以全志A64为实例,分析UART驱动以及浅谈TTY架构. linux-3.10/drive ...
- C# 反射之SqlDatareader转换为Model实体.
虽说反射的效率比较低,但是在当今的时代,盛行的大数据,以及高并发的产生,硬件的产能正在逐渐的提升,所以我们可以用空间来换取时间.反射所消耗的那些性能问题其实在企业级开发而言也就无所谓了.二 : 反射得 ...
- jmeter ---单个server最大连接数的设置
为了模拟浏览器关于建立多少并行的链接设置,在jmeter中也有相关的设置 在HTTP请求设置页面,勾选“Use concurrent pool" 选型,并将pool size设置为所需的并发 ...
- laravel 二维码生成器包 QrCode 的使用
在laravel中使用 QrCode 生成二维码 https://laravelacademy.org/post/2605.html 我在本机的windows下composer require 没有成 ...
- week01—绪论
一.作业题目 仿照三元组或复数的抽象数据类型写出有理数抽象数据类型的描述 (有理数是其分子.分母均为整数且分母不为零的分数). 有理数基本运算: 构造有理数T,元素e1,e2分别被赋以分子.分母值 销 ...
- (转)IE=EmulateIE7 标签的作用
本文转载自:http://www.cnblogs.com/0000/archive/2009/11/01/1593851.html 对于 Web 开发人员来说,文本兼容性是一个要考虑的重要问题.Win ...
- 校赛热身赛 Problem D. Unsolved Mystery
Problem D. Unsolved MysteryThe world famous mathematician Wang Hao published a paper recently in the ...