当前位置:网站首页>QT笔记——自定义的流式布局QFlowLayout
QT笔记——自定义的流式布局QFlowLayout
2022-07-20 06:48:00 【旧街凉风°】
想要实现一个流式布局,如下:
就在网上搜索了 关于流式布局的相关例子
代码如下:
QFlowLayout.h
#pragma once
#include <QLayout>
#include <QStyle>
class QFlowLayout : public QLayout
{
Q_OBJECT
public:
explicit QFlowLayout(QWidget* parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
explicit QFlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~QFlowLayout();
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;
private:
int doLayout(const QRect& rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
private:
QList<QLayoutItem*> itemList; //layout的子项
int m_hSpace;
int m_vSpace;
};
QFlowLayout.cpp
#include <QWidget>
#include "QFlowLayout.h"
QFlowLayout::QFlowLayout(QWidget* parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin); // 边缘间距
}
QFlowLayout::QFlowLayout(int margin, int hSpacing, int vSpacing)
: m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
QFlowLayout::~QFlowLayout()
{
QLayoutItem* item;
// 内部所有内容析构
while ((item = takeAt(0)))
delete item;
}
void QFlowLayout::addItem(QLayoutItem* item)
{
itemList.append(item); // 将项目添加到布局
}
int QFlowLayout::horizontalSpacing() const
{
// 小部件之间的间距
if (m_hSpace >= 0) {
return m_hSpace;
}
else {
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing); // 在没有间隔的时候自动智能生成一段间隔
}
}
int QFlowLayout::verticalSpacing() const
{
if (m_vSpace >= 0) {
return m_vSpace;
}
else {
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
}
int QFlowLayout::count() const
{
return itemList.size(); // 返回布局中的项目数
}
QLayoutItem* QFlowLayout::itemAt(int index) const
{
return itemList.value(index);
}
QLayoutItem* QFlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index); // 删除并返回项目, 如果某个项目被删除,其余的项目将被重新编号。
return nullptr;
}
Qt::Orientations QFlowLayout::expandingDirections() const
{
return 0;
}
bool QFlowLayout::hasHeightForWidth() const
{
return true;
}
int QFlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true); // 高度取决于宽度的窗口小部件
return height;
}
void QFlowLayout::setGeometry(const QRect& rect)
{
// 计算布局项目的几何形状
QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize QFlowLayout::sizeHint() const
{
return minimumSize();
}
QSize QFlowLayout::minimumSize() const
{
QSize size;
for (const QLayoutItem* item : qAsConst(itemList))
size = size.expandedTo(item->minimumSize());
const QMargins margins = contentsMargins();
size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
return size;
}
int QFlowLayout::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;
for (QLayoutItem* item : qAsConst(itemList)) {
const 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; // 下一个item的x坐标
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
// 当前item的x坐标超过边界
// 设置为下一行的第一个
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 QFlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
// 当父是QWidget=>顶层布局的默认间距为pm样式。
// 当父为QLayout=>子布局的默认间距由父布局的间距来确定。
QObject* parent = this->parent();
if (!parent) {
return -1;
}
else if (parent->isWidgetType()) {
QWidget* pw = static_cast<QWidget*>(parent);
return pw->style()->pixelMetric(pm, nullptr, pw);
}
else {
return static_cast<QLayout*>(parent)->spacing();
}
}
QFlowLayoutTest.cpp
#include "QFlowLayoutTest.h"
QFlowLayoutTest::QFlowLayoutTest(QWidget* parent)
: QWidget(parent)
{
ui.setupUi(this);
flowLayout = new QFlowLayout(this,20,20,20);
for (int i = 0; i < 10; i++)
{
QPushButton* p = new QPushButton(QString::number(i));
p->setFixedSize(80, 40);
this->flowLayout->addWidget(p);
}
}
参考博客:
调整的流式布局的BUG
流式布局
边栏推荐
- 人人代码生成器--简化你的开发
- 2022-07-19:f(i) : i的所有因子,每个因子都平方之后,累加起来。 比如f(10) = 1平方 + 2平方 + 5平方 + 10平方 = 1 + 4 + 25 + 100 = 130。
- FigDraw 15. Omiccircos of SCI article drawing
- 【Jailhouse 文章】Certify the Uncertified Towards Assessment of Virtualization for Mixed-criticality...
- 2022.07.19(LC_剑指 Offer II 041. 滑动窗口的平均值)
- DNA 10. Identify oncodrivecluster
- QQ Three Party login - pre environment and interaction
- 【详细教程】一文参透 MongoDB 聚合查询
- 如果在加密领域有段位,你是“青铜”还是“王者”?
- redis锁超卖解决问题
猜你喜欢
编程与哲学(1)
What are the six access database objects? What is the most important difference between access and excel?
kubernetes部署单节点Redis服务
已解决(最新版selenium报错)AttributeError: module ‘selenium.webdriver‘ has no attribute ‘PhantomJS‘
Renren code generator -- simplify your development
redis锁超卖解决问题
Unlock high scores | eBay deepens user experience and optimizes large screen device applications
C language file operation management (Part 2)
自编码器(Auto-Encoder)
FigDraw 11. Violinplot of SCI article drawing
随机推荐
Write a Book class that has at least two attributes: name and price.
已解决(最新版selenium报错)AttributeError: module ‘selenium.webdriver‘ has no attribute ‘PhantomJS‘
threeJS中dat.gui的使用显示文件夹点击时候及调色器
二维卷积中文微博情感分类项目
À propos des outils d'édition XML
C语言结构体柔型数组
【LeetCode】206. 反转链表
尚医通项目总结
HCIP-7. LSA header of OSPF
《PolarDB for Postgres SQL 》主要讲了什么?
Redis的五种数据类型详解
C# 反射与工厂模式
【学习笔记】ARC144
OTA online upgrade practice record (still need to be updated)
【LeetCode】206. Reverse linked list
The direction of this
FigDraw 14. Chord diagram of SCI article drawing and article reproduction (chord diagram)
[MySQL] temporary table & View
Docker 学习笔记(十二)-- 部署Redis集群 实战
[cloud native kubernetes] how to use the initialization container under the kubernetes cluster