Qt图形视图框架:自定义流式布局

编写自定义布局需要继承QGraphicsLayout,然后实现如下函数:

  • setGeometry():布局的几何形状。
  • sizeHint():布局大小提示
  • count():项目数量
  • itemAt():根据索引获取项
  • removeAt():从布局中删除索引项。

代码如下:

#ifndef GRAPHICSFLOWLAYOUT_H
#define GRAPHICSFLOWLAYOUT_H

#include <QGraphicsLayout>
#include <QList>

class GraphicsFlowLayout : public QGraphicsLayout
{
public:
    GraphicsFlowLayout(QGraphicsLayoutItem *parent = nullptr);
    ~GraphicsFlowLayout();
    virtual int count() const override;
    virtual void removeAt(int index)override;
    virtual QGraphicsLayoutItem *itemAt(int index) const override;
    virtual void setGeometry(const QRectF &rect)override;
    void addItem(QGraphicsLayoutItem * item);
protected:
    virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override;
private:
    QList<QGraphicsLayoutItem*> itemList;
};

#endif // GRAPHICSFLOWLAYOUT_H
#include "graphicsflowlayout.h"
#include <QDebug>

GraphicsFlowLayout::GraphicsFlowLayout(QGraphicsLayoutItem *parent)
    :QGraphicsLayout(parent)
{

}

GraphicsFlowLayout::~GraphicsFlowLayout()
{
    foreach (auto item, itemList)
    {
        if(item->ownedByLayout())
            delete item;
    }
}

void GraphicsFlowLayout::addItem(QGraphicsLayoutItem * item)
{
    itemList.append(item);
    invalidate();
}

int GraphicsFlowLayout::count() const
{
    return itemList.size();
}

void GraphicsFlowLayout::removeAt(int index)
{
    if(index >= 0 && index < itemList.size())
    {
        auto item = itemList.at(index);
        itemList.removeOne(item);
        delete item;
        invalidate();
    }
}

QGraphicsLayoutItem *GraphicsFlowLayout::itemAt(int index) const
{
    return (index >= 0 && index < itemList.size()) ? itemList.at(index) : nullptr;
}

QSizeF GraphicsFlowLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    QSizeF size;
    foreach (auto item, itemList)
    {
        QSizeF itemSize;
        switch ( which )
        {
            case Qt::MinimumSize:
                itemSize = item->minimumSize();break;
            case Qt::PreferredSize:
                itemSize = item->preferredSize();break;
            case Qt::MaximumSize:
                itemSize = item->maximumSize();break;
            default:
                itemSize = constraint;
        }

        size = size.expandedTo(itemSize);
    }
    size += QSize(20, 20);
    size.setHeight(size.height() * 4);
    if(size.height() < 100)
        size.setHeight(100);
    return size;
}

void GraphicsFlowLayout::setGeometry(const QRectF &rect)
{
//    QGraphicsLayout::setGeometry(rect);
    qreal left, top, right, bottom;
    getContentsMargins(&left, &top, &right, &bottom);//获取布局目前的上下左右边距值
    QRectF effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
    qreal x = effectiveRect.x();
    qreal y = effectiveRect.y();
    qreal lineHeight = 0;
    foreach (auto item, itemList)
    {
        qreal spaceX = 15;
        qreal spaceY = 15;

        auto size = item->preferredSize();
        qreal nextX = x + size.width() + spaceX;
        if (nextX - spaceX > effectiveRect.right() && lineHeight > 0)
        {
            x = effectiveRect.x();
            y = y + lineHeight + spaceY;
            nextX = x + size.width() + spaceX;
            lineHeight = 0;
        }

        item->setGeometry(QRectF(QPointF(x, y), size));

        x = nextX;
        lineHeight = qMax(lineHeight, size.height());
    }
}

效果:

    GraphicsFlowLayout * flowLayout = new GraphicsFlowLayout;
    flowLayout->addItem(new sliderGraphicsPixmapItem(true,"",Qt::Horizontal));
    flowLayout->addItem(new sliderGraphicsPixmapItem(true,"",Qt::Horizontal));
    flowLayout->addItem(new sliderGraphicsPixmapItem(true,"",Qt::Horizontal));
    flowLayout->addItem(new sliderGraphicsPixmapItem(true,"",Qt::Horizontal));

    GraphicsProxyWidget *form = new GraphicsProxyWidget;
    form->setCenterLayout(flowLayout);
    gphs->addItem(form);

放入布局的布局项要设置最小尺寸。效果并不是特别完美,仅供有需要的同志参考。

相关博文:

Qt图形视图框架:QGraphicsLayout

Qt图形视图框架:将自定义图形项放入布局

更新:发现Qt的demo里面带了图形视图框架流式布局的...,示例界面搜“Graphics View Flow Layout Example”这个就是......

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值