编写自定义布局需要继承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的demo里面带了图形视图框架流式布局的...,示例界面搜“Graphics View Flow Layout Example”这个就是......