先上代码:

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(QWidget *parent, bool home,int margin = -1, int hSpacing = -1, int vSpacing = -1 );explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);~FlowLayout();public:void addItem(QLayoutItem *item) Q_DECL_OVERRIDE;int horizontalSpacing() const;int verticalSpacing() const;Qt::Orientations expandingDirections() const Q_DECL_OVERRIDE;bool hasHeightForWidth() const Q_DECL_OVERRIDE;int heightForWidth(int) const Q_DECL_OVERRIDE;int count() const Q_DECL_OVERRIDE;QLayoutItem *itemAt(int index) const Q_DECL_OVERRIDE;QSize minimumSize() const Q_DECL_OVERRIDE;void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;QSize sizeHint() const Q_DECL_OVERRIDE;QLayoutItem *takeAt(int index) Q_DECL_OVERRIDE;int fillSpaceX(QWidget *wid) const;private:int doLayout(const QRect &rect, bool testOnly) const;int smartSpacing(QStyle::PixelMetric pm) const;private:QList<QLayoutItem *> itemList;int m_hSpace;int m_vSpace;bool m_home = false;};

flowlayout.cpp:

#include "flowlayout.h"#include <QWidget>
#include <QDebug>
#include <QtMath>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(QWidget *parent, bool home, int margin, int hSpacing, int vSpacing):QLayout(parent),m_hSpace(hSpacing),m_vSpace(vSpacing),m_home(home)
{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))) {}
}void FlowLayout::addItem(QLayoutItem *item){itemList.append(item);
}int FlowLayout::horizontalSpacing() const{if (m_hSpace >= 0 || m_hSpace == -1) {return m_hSpace;} else {return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);}
}int FlowLayout::verticalSpacing() const{if (m_vSpace >= 0 || m_vSpace == -1) {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;int fillX = 0;bool bFillX = false;QLayoutItem *item;foreach (item, itemList) {QWidget *wid = item->widget();int spaceX = horizontalSpacing();if (spaceX == -1) {if (!bFillX) {bFillX = true;fillX = fillSpaceX(wid);}spaceX = fillX;}int spaceY = verticalSpacing();if (spaceY == -1 && fillX >= 0) {spaceY = fillX;} else {spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);}if (m_home) {spaceY = 32;}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();}
}int FlowLayout::fillSpaceX(QWidget *wid) const{int num = 0;int x = 0;int numH = 0;int space  = 4;if (m_home) {space = 24;}int len = this->parentWidget()->width() - this->contentsMargins().left() - this->contentsMargins().right();while (true) {num++;if (num * (wid->width() + space) - space >= len) {  //最小间距spacebreak;}}num = num - 1;if (num <= 1) {numH = itemList.size();return 32;}int height = wid->height();numH = ceil(double(itemList.size()) / num);x = len + space - num * (wid->width() + space);x = ceil(double(x)/(num - 1)) +space;x = x - 1;   //考虑边框等因素影响int maxY = numH * (height + x) + 32 - x;if (m_home) {maxY = numH * (height + 24) + 32;}this->parentWidget()->setFixedHeight(maxY);return x;
}

使用效果一:

FlowLayout * flowLayout = new FlowLayout(ui->widget_2, true, 0);
flowLayout->setContentsMargins(70, 0, 70, 0);
/*.....*/
flowLayout->addWidget(baseWidget);

使用效果二:

picFlowLayout = new FlowLayout(ui->picFrame,16, -1, -1);
ui->picFrame->setLayout(picFlowLayout);
/*.....................*/
picFlowLayout->addWidget(picUnit);

注意,不能直接在滚动控件的widget里面去设置这个flowLayout,否则可能会导致在改变大小的时候出现段错误(一直循环在修改size)。例如在效果一中,如果直接设置父对象为scrollAreaWidgetContents_5,当在首页改变控制面板窗口大小时,就会出现闪退的情况,所以这里添加了一个widget。使用QT提供的flowlayout不会有此问题,猜测是因为新加的fillSpaceX()函数中会修改父窗口的高度导致。

Qt使用flowlayout,使控件两端间距始终固定,垂直和水平间距相等相关推荐

  1. Qt QWidget实现开关控件SwithButton(SlipButton)

    前言 Qt做界面的时候常常会用到开关控件,类似于CheckButton有两种状态,只是界面表现形式不一样而已.本文通过QWidget类来实现一个开关控件SwitchBtn(有些平台上又称为SlipBu ...

  2. 【Android自定义View实战】之自定义评价打分控件RatingBar,可以自定义星星大小和间距...

    [Android自定义View实战]之自定义评价打分控件RatingBar,可以自定义星星大小和间距

  3. MFC如何使控件大小随着对话框大小自动调整

    MFC如何使控件大小随着对话框大小自动调整 2012-04-27 16:24:50|  分类: MFC |  标签: |字号大中小 订阅 对话框的大小变化后,假若对话框上的控件大小不变化,看起来会比较 ...

  4. 使控件拥有透明背景色 [引用]

    默认情况下,控件不支持透明背景色.但是,通过使用构造函数中的 Control.SetStyle 方法,可以让控件拥有不透明.透明或半透明的背景色.Control 类的 SetStyle 方法用于为控件 ...

  5. 怎样使控件的背景色为透明色?

    要使控件的背景色为透明色,只需要在窗体初始化,或实体load方法中加上如下代码即可: SetStyle(ControlStyles.SupportsTransparentBackColor, true ...

  6. VS+QT开发Ocx/ActiveX控件 一

    VS+QT开发Ocx/ActiveX控件 一 VS+QT开发Ocx/ActiveX控件-------网页中全屏 二 QT开发ActiveX控件 一:所用IDE版本,需用管理员权限 二:创建Active ...

  7. Qt开发Activex笔记(二):Qt调用Qt开发的Activex控件

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789693 长期持续带来更多项目与技术分 ...

  8. python使用wx绘界面,布局自已的toolbar,使控件右对齐

    正确的右对齐方法: panel = wx.Panel(self) button = wx.Button(panel, label = _(u'确定'), size = (60, 28))hbox = ...

  9. QT QSpinBox 整数计数器控件 使用详解

    本文详细的介绍了QSpinBox控件的各种操作,例如:获取数值.设置前后缀.设置最大/小值.进制转换.关联信号槽.优化信号.QSS优化.文件源码.样式表 .效果:可以设置背景.边框.向上按钮.向下按钮 ...

  10. QT自定义控件之倒计时控件

    文章目录 1 效果预览 2 加载背景图片 3 尺子可拉动头部的实现 4 整个尺子部分的实现 5 表盘的实现 6 主界面代码实现 1 效果预览 我们首先来看下实现的效果: 右边的表带拉动会使左边的表盘跟 ...

最新文章

  1. CNN卷积神经网络可视化:可交互有细节,卷积ReLU池化都一目了然
  2. 运行SSIS包的几种方式
  3. FastDFS_install_document_detail
  4. ST函数(ST表)RMQ O(1)查询 离线
  5. 数据特征分析-对比分析
  6. Python求解进制问题(阿里巴巴2015笔试题)
  7. java正则 链接_Java使用正则表达式匹配获取链接地址的方法示例
  8. 测试用例集-11.QQ表情收藏功能测试用例
  9. 过程改进的疑惑 - 习惯能改么?
  10. [渝粤教育] 四川大学 西方经济学(微观) 参考 资料
  11. tnl分析笔记之 CORBA 与假装自己是 CORBA
  12. CDH 端口未授权访问:hdfs-50070, yarn-8088, jetty漏洞修复
  13. FastJson1.2.24反序列化导致任意命令执行漏洞复现(CVE-2017-18349)
  14. [Swift]LeetCode1104. 二叉树寻路 | Path In Zigzag Labelled Binary Tree
  15. 网御星云防火墙上网行为审计配置
  16. CSGO服务器租用如何选择合适的配置?CSGO服务器怎么选择?
  17. 黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(3)暴力破解目录与文件位置
  18. 网络安全菜鸟学习之漏洞篇——文件包含漏洞
  19. 环保部启动调查甘肃陇星锑业公司尾砂泄漏事件
  20. python ANN人工神经网络手写字图像识别(成功运行)

热门文章

  1. 上下调基因和代谢物--不同颜色显示在同一张KEGG通路图中
  2. wps ppt word 双屏幕同时浏览技巧
  3. C编程入门到精通 F1: 学习本课程常见问题说明
  4. Bootstrap框架
  5. 非确定有限自动机转换为确定有限自动机
  6. 鬼谷八荒宗门亲密度怎么提升
  7. 长ping域名带时间戳
  8. gtx1060 能用catia软件吗_性能炸天!资深IT大叔详测Precision 7730工作站
  9. LiveData setValue和postValue的区别及详解
  10. node下运行js文件实时更新文件变化