目标:

        

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来完成布局。的更多相关文章

  1. 自定义View(7)官方教程:自定义View(含onMeasure),自定义一个Layout(混合组件),重写一个现有组件

    Custom Components In this document The Basic Approach Fully Customized Components Compound Controls ...

  2. 自定义View Layout过程 (3)

    目录 目录 1. 知识基础 具体请看我写的另外一篇文章:(1)自定义View基础 - 最易懂的自定义View原理系列 2. 作用 计算View视图的位置. 即计算View的四个顶点位置:Left.To ...

  3. Customize the View Items Layout 自定义视图项目布局

    In this lesson, you will learn how to customize the default editor layout in a Detail View. For this ...

  4. 自定义一个更好用的SwipeRefreshLayout(弹力拉伸效果详解)(转载)

    转自: 自定义一个更好用的SwipeRefreshLayout(弹力拉伸效果详解) 前言 熟悉SwipeRefreshLayout的同学一定知道,SwipeRefreshLayout是android里 ...

  5. 在Dynamics CRM中自定义一个通用的查看编辑注释页面

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复162或者20151016可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 注释在CRM中的显示是比较特别, ...

  6. [WPF 自定义控件]自定义一个“传统”的 Validation.ErrorTemplate

    1. 什么是Validaion.ErrorTemplate 数据绑定模型允许您将与您Binding的对象相关联ValidationRules. 如果用户输入的值无效,你可能希望在应用程序 用户界面 ( ...

  7. 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 ...

  8. SpringMVC 自定义一个拦截器

    自定义一个拦截器方法,实现HandlerInterceptor方法 public class FirstInterceptor implements HandlerInterceptor{ /** * ...

  9. jQuery Validate 表单验证插件----自定义一个验证方法

    一.下载依赖包 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW  访问密码 f224 二.引入依赖包 <script src="../../scripts/j ...

随机推荐

  1. Spring IOC容器的初始化—(一)Resource定位

    前言 上一篇博文“ Spring IOC是怎样启动的 ”中提到了refresh()方法,这个就是容器初始化的入口.容器初始化共有三个阶段: 第一阶段:Resource定位 第二阶段:BeanDefin ...

  2. openfaas 私有镜像配置

    备注: 此项目是使用nodejs  生成唯一id 的\ 预备环境 docker harbor faas-cli openfaas k8s 1. 项目初始化 faas-cli new node --la ...

  3. loj 572 Misaka Network 与求和 —— min_25筛

    题目:https://loj.ac/problem/572 推式子:https://www.cnblogs.com/cjoieryl/p/10150718.html 又学习了一下杜教筛hh: 原来 u ...

  4. gen already exists but is not a source folder

    遇到android项目导入出现后重复空包等错误,往往是导入的java编译级别有关,点击项目properties-> java Compiler ->修改Compiler complianc ...

  5. form表单中name和id区别

    HTML文本是由HTML命令组成的描述性文本,HTML命令可以说明文字.图形.动画.声音.表格.链接等.HTML的结构包括头部(Head).主体(Body)两大部分,其中头部描述浏览器所需的信息,而主 ...

  6. CAN总线概述

    基本概念 CAN 是Controller Area Network 的缩写(以下称为CAN),是ISO国际标准化的串行通信协议.在汽车产业中,出于对安全性.舒适性.方便性.低公害.低成本的要求,各种各 ...

  7. Java [parms/options] range -b 100 -c 10 -i 100 -t 300 -s 180

    3 down vote Just run the command java -X and you will get ans of all_ C:\Users\Admin>java -X -Xmi ...

  8. web deploy 部署网站

    一.服务端配置 1. 确保在服务器端(我目前是win server 2012 R2)安装管理服务 安装后服务器会重启, 2)安装webdeploy http://www.iis.net/downloa ...

  9. Tulpar-web渗透小工具

    首先git clone一下,项目地址:https://github.com/anilbaranyelken/tulpar 下载完后打开文件 然后安装所需的Python模块 安装完成后先看一下帮助 命令 ...

  10. MFC 文档/视图

    1.文档修改后,关闭时需要保存,主要用到2个函数,在需要更改文档内容的函数里调用SetModifiedFlag(TRUE),另一个就是SaveModified()函数,简单的例子: BOOL CMFC ...