Qt Widgets流式布局Demo

时间如流水,只能流去不流回!

点赞再看,养成习惯,这是您给我创作的动力!

本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform、WPF、ASP.NET Core等,亦有C++桌面相关的Qt Quick和Qt Widgets等,只分享自己熟悉的、自己会的。

阅读导航:

  • 一、先看效果
  • 二、本文背景
  • 三、代码实现
  • 四、文章参考
  • 五、代码下载

一、先看效果

Qt Widgets流式布局Demo

二、本文背景

年初帮一个网友写的例子,布局容器是在网上找的,例子中图片由该网友提供。

三、代码实现

核心代码是布局容器

FlowLayout.h

#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H

#include <QLayout>
#include <QRect>
#include <QStyle>

#include <QLayout>
#include <QRect>
#include <QStyle>

class QFlowLayout : public QLayout
{
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 *> x_itemList;
    int x_hSpace;
    int x_vSpace;
};
#endif

FlowLayout.cpp

#include "FlowLayout.h"

#include <algorithm>
#include <QWidget>

QFlowLayout::QFlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
    : QLayout(parent),
    x_hSpace(hSpacing),
    x_vSpace(vSpacing)
{
    setContentsMargins(margin, margin, margin, margin);
}

QFlowLayout::QFlowLayout(int margin, int hSpacing, int vSpacing)
    : x_hSpace(hSpacing),
    x_vSpace(vSpacing)
{
    setContentsMargins(margin, margin, margin, margin);
}

QFlowLayout::~QFlowLayout()
{
    QLayoutItem *item;
    while ((item = takeAt(0)))
        delete item;
}

void QFlowLayout::addItem(QLayoutItem *item)
{
    x_itemList.append(item);
}

int QFlowLayout::horizontalSpacing() const
{
    if (x_hSpace >= 0)
    {
        return x_hSpace;
    }
    else
    {
        return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
    }
}

int QFlowLayout::verticalSpacing() const
{
    if (x_vSpace >= 0) {
        return x_vSpace;
    }
    else {
        return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
    }
}

int QFlowLayout::count() const
{
    return x_itemList.size();
}

QLayoutItem *QFlowLayout::itemAt(int index) const
{
    return x_itemList.value(index);
}

QLayoutItem *QFlowLayout::takeAt(int index)
{
    if (index >= 0 && index < x_itemList.size())
        return x_itemList.takeAt(index);
    else
        return 0;
}

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;
    QLayoutItem *item;
    foreach(item, x_itemList)
        size = size.expandedTo(item->minimumSize());

    size += QSize(2 * margin(), 2 * margin());
    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;

    QLayoutItem *item;
    foreach(item, x_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 QFlowLayout::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();
    }
}

添加菜单块的代码form.cpp

#include "form.h"
#include "ui_form.h"
#include "FlowLayout.h"
#include <QToolButton>
#include <QImage>
#include <QPixmap>

Form::Form(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Form),
    m_pFlowLayout(new QFlowLayout(this))
{
    ui->setupUi(this);

    addButton("照片", ":/images/picture.png");
    addButton("视频", ":/images/video.png");
    addButton("日历", ":/images/calendar.png");
    addButton("语言", ":/images/language.png");
    addButton("摄像头", ":/images/camera.png");
    addButton("录像设置", ":/images/video_setting.png");
    addButton("关于系统", ":/images/about_system.png");
    addButton("关闭", ":/images/colose.png");
}

void Form::addButton(const QString &title, const QString &imgPath) {
    QToolButton *btn = new QToolButton(this);

    btn->setText(title);

    QImage image;
    image.load(imgPath);
    QPixmap pixmap = QPixmap::fromImage(image);
    btn->setIcon(QIcon(pixmap));
    btn->setIconSize(QSize(80, 80));

    btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);

    m_pFlowLayout->addWidget(btn);
}

Form::~Form()
{
    delete ui;
}

四、文章参考

忘了出处了,不好意思,谢谢作者。

五、代码下载

CSDN: https://download.csdn.net/download/henrymoore/11588697

除非注明,文章均由 Dotnet9 整理发布,欢迎转载。

转载请注明:
作者:Dotnet9
链接:https://dotnet9.com/6226.html
来源:Dotnet9
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

发表评论

登录后才能评论