简述

有时候我们希望窗口内的布局随着窗口大小的改变而自动调整,这就是流式布局(FlowLayout)的作用。

流式布局会根据窗口的尺寸来自动调整控件布局,控件的排布会随着窗口宽度的变化而变化。

使用

流式布局(FlowLayout)不是Qt的标准布局类,而是以源码的形式供我们参考使用。

效果

随着主窗宽度的改变,控件的布局也随之变化

源码

flowlayout.h

#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H#include <QLayout>
#include <QRect>
#include <QStyle>
class FlowLayout : public QLayout
{public:explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);~FlowLayout();void addItem(QLayoutItem *item) override;int horizontalSpacing() const;int verticalSpacing() const;Qt::Orientations expandingDirections() const override;bool hasHeightForWidth() const override;int heightForWidth(int) const override;int count() const override;QLayoutItem *itemAt(int index) const override;QSize minimumSize() const override;void setGeometry(const QRect &rect) override;QSize sizeHint() const override;QLayoutItem *takeAt(int index) override;private:int doLayout(const QRect &rect, bool testOnly) const;int smartSpacing(QStyle::PixelMetric pm) const;QList<QLayoutItem *> itemList;int m_hSpace;int m_vSpace;
};#endif // FLOWLAYOUT_H

flowlayout.cpp

#include <QtWidgets>#include "flowlayout.h"
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing): QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{setContentsMargins(margin, margin, margin, margin);
}FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing): m_hSpace(hSpacing), m_vSpace(vSpacing)
{setContentsMargins(margin, margin, margin, margin);
}FlowLayout::~FlowLayout()
{QLayoutItem *item;while ((item = takeAt(0)))delete item;
}void FlowLayout::addItem(QLayoutItem *item)
{itemList.append(item);
}int FlowLayout::horizontalSpacing() const
{if (m_hSpace >= 0) {return m_hSpace;} else {return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);}
}int FlowLayout::verticalSpacing() const
{if (m_vSpace >= 0) {return m_vSpace;} else {return smartSpacing(QStyle::PM_LayoutVerticalSpacing);}
}int FlowLayout::count() const
{return itemList.size();
}QLayoutItem *FlowLayout::itemAt(int index) const
{return itemList.value(index);
}QLayoutItem *FlowLayout::takeAt(int index)
{if (index >= 0 && index < itemList.size())return itemList.takeAt(index);elsereturn 0;
}Qt::Orientations FlowLayout::expandingDirections() const
{return 0;
}bool FlowLayout::hasHeightForWidth() const
{return true;
}int FlowLayout::heightForWidth(int width) const
{int height = doLayout(QRect(0, 0, width, 0), true);return height;
}void FlowLayout::setGeometry(const QRect &rect)
{QLayout::setGeometry(rect);doLayout(rect, false);
}QSize FlowLayout::sizeHint() const
{return minimumSize();
}QSize FlowLayout::minimumSize() const
{QSize size;QLayoutItem *item;foreach (item, itemList)size = size.expandedTo(item->minimumSize());size += QSize(2*margin(), 2*margin());return size;
}int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{int left, top, right, bottom;getContentsMargins(&left, &top, &right, &bottom);QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);int x = effectiveRect.x();int y = effectiveRect.y();int lineHeight = 0;QLayoutItem *item;foreach (item, itemList) {QWidget *wid = item->widget();int spaceX = horizontalSpacing();if (spaceX == -1)spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);int spaceY = verticalSpacing();if (spaceY == -1)spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);int nextX = x + item->sizeHint().width() + spaceX;if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {x = effectiveRect.x();y = y + lineHeight + spaceY;nextX = x + item->sizeHint().width() + spaceX;lineHeight = 0;}if (!testOnly)item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));x = nextX;lineHeight = qMax(lineHeight, item->sizeHint().height());}return y + lineHeight - rect.y() + bottom;
}
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{QObject *parent = this->parent();if (!parent) {return -1;} else if (parent->isWidgetType()) {QWidget *pw = static_cast<QWidget *>(parent);return pw->style()->pixelMetric(pm, 0, pw);} else {return static_cast<QLayout *>(parent)->spacing();}
}

引用


[1] Qt助手

Qt之流式布局(FlowLayout)相关推荐

  1. 常用的流式布局FlowLayout

    流式布局FlowLayout 代码示例: package Test;import javax.swing.*; import java.awt.*;public class FlowLayoutTes ...

  2. 流式布局FlowLayout支持行数控制,单选,多选,点击等操作

    最近有这么一个需求,如下图 开发中内容搜索页面经常会记录搜索关键字,搜索关键字长度不一,我们通过会采用自定义流布局的方式展示:流布局的基本需要是动态添加childView并实现自动换行操作,这个操作比 ...

  3. android 自定义flowlayout,Android 流式布局FlowLayout 实现关键字标签

    FlowLayout Android 流式布局FlowLayout 实现关键字标签 效果图 使用方法 在项目根目录的build.gradle文件中加入如下代码 maven { url "ht ...

  4. Android自定义流式布局-FlowLayout

    很多App在搜索页时都有对热门标签的一个排列,而Android官方没有对应的布局控件,所以自己写了一个流式布局(也称标签布局)--FlowLayout. 为了大家使用的方便,没有添加自定义属性,所以需 ...

  5. Android流式布局FlowLayout,一款针对Tag的布局

    交流群 : 668524118 本群主要用于编程技术 ,及创意作品 ,思维架构的交流 ,欢迎喜欢创新 ,热爱生活的朋友加入 ! 前言 flow layout, 流式布局, 这个概念在移动端或者前端开发 ...

  6. Android第三方流式布局FlowLayout简单实用(搜索历史记录)

    效果图: 导入大Model下: maven { url 'https://jitpack.io' } builde.gradle依赖: implementation 'com.github.LRH19 ...

  7. 手写一个淘宝、京东的搜索流式布局FlowLayout

    目录 一些叨叨 继承ViewGrop 实现自定义控件 重写构造器 提供对外接口 测量 摆放 使用方法 完整代码 一些叨叨 市面上所有的app只要有搜索功能,几乎都离不开流式布局,像淘宝.京东.小红书等 ...

  8. Android中的封装流式布局FlowLayout

    鸿洋的GitHub:https://github.com/hongyangAndroid/FlowLayout 第一步:加依赖 implementation 'com.hyman:flowlayout ...

  9. 流式布局FlowLayout使用

    参考自:地址传送 特色 以setAdapter形式注入数据 直接设置selector为background即可完成标签选则的切换,类似CheckBox 支持控制选择的Tag数量,比如:单选.多选 支持 ...

最新文章

  1. Divan and a Store 贪心(800)
  2. python在人工智能应用锁_解读! Python在人工智能中的作用
  3. html div转换图片
  4. 机器阅读理解中文章和问题的深度学习表示方法
  5. Blueprint:一个Flash Builder代码示例的扩展
  6. ubuntu 64 12.04 oracle,ubuntu server 12.04 x86_64 下安装oracle xe 11 x86_64
  7. beego——模板处理
  8. 本周ASP.NET英文技术文章推荐[??/?? - 09/22]:VS 2008、.NET 3.5、asp:ListView、DotNetNuke、ASP.NET AJAX...
  9. 手把手教你如何罗列提纲,避开这3个坑,提升写作效率50%
  10. 设计模式精髓—封装变化
  11. dyld 加载 Mach-O
  12. 苹果ppt_“苹果美感中国学不来?”阿里、腾讯的设计师让你感受中国智造
  13. 数学史思维导图_如何学好高中数学,看懂思维导图,秒懂系列之集合
  14. 史上最完整的Android开发工具集合(附带下载地址)
  15. vue 动态面包屑 通过面包屑带参数跨级跳转 面包屑动态标题 多级路由嵌套设置默认页面和隐藏左侧导航栏显示
  16. 浅谈soul网关架构图
  17. 腾讯云学生机官网地址在哪里?
  18. 使用JDK的 keytool 生成JKS,修改查看JKS信息
  19. aws saa是什么缩写?aws saa认证考察什么?
  20. 国际名品SYSTEM入驻北京金融街购物中心__购物败家_YOKA时尚网

热门文章

  1. ORACLE存储过程RECORD数据类型的使用
  2. iocp端口断开_在完成端口IOCP模型判断客户端是否已关闭连接(掉线) | 学步园
  3. bim计算机工程师考试,BIM工程师怎么报考?
  4. 【C++FunCode】基于Funcode使用C++语言编写小游戏(小鲨鱼历险记)
  5. HackMyvm(三)Hotel持续更新
  6. CSS3中的关键帧@keyframes 和 动画animation
  7. 编译原理学习笔记(二十六)~习题:构造基于LR(0)、LR(1)项目的识别活前缀的DFA
  8. 开发微信公众号支付代码
  9. Docker-配置私有仓库
  10. Android人脸识别和证件识别