简述
手动布局另一种方法是通过继承QLayout类编写自己的布局管理器。
下面我们详细来举一个例子-QCardLayout。它由同名的Java布局管理器启发而来。也被称之为卡片布局,每个项目偏移QLayout::spacing()。
定义
编写自己的布局,必须定义如下:
一种存储布局处理项目的数据结构,每个项目都是一个QLayoutItem,本例使用QList。
addItem() 如何添加项目布局。
setGeometry() 如何控制布局。
sizeHint() 布局的优选大小。
itemAt() 如何遍历布局。
takeAt() 如何删除布局中的项目。
大多数情况下,也会实现的minimumSize()。
实现
效果
源码
QCardLayoud.h
#ifndef QCARDLAYOUT_H
#define QCARDLAYOUT_H
#include <QWidget>
#include <QLayout>
#include <QLayoutItem>
class QCardLayout : public QLayout
{
public:
QCardLayout(QWidget *parent = 0);
~QCardLayout();
void addItem(QLayoutItem *item);
QSize sizeHint() const;
QSize minimumSize() const;
int count() const;
QLayoutItem *itemAt(int) const;
QLayoutItem *takeAt(int);
void setGeometry(const QRect &rect);
private:
QList<QLayoutItem*> list;
};
#endif //QCARDLAYOUT_H
QCardLayoud.cpp
#include "QCardLayout.h"
QCardLayout::QCardLayout(QWidget *parent)
: QLayout(parent)
{
}
// 由于QLayoutItem不继承自QObject,必须手动删除。在析构函数中,使用takeAt()删除列表中的每个项目,然后将其删除。
QCardLayout::~QCardLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}
// 获取列表中的项目数
int QCardLayout::count() const
{
return list.size();
}
// 获取索引idx所对应的项目
QLayoutItem *QCardLayout::itemAt(int idx) const
{
return list.value(idx);
}
// 移除索引idx所对应的项目,并返回
QLayoutItem *QCardLayout::takeAt(int idx)
{
return idx >= 0 && idx < list.size() ? list.takeAt(idx) : 0;
}
// 添加项目
void QCardLayout::addItem(QLayoutItem *item)
{
list.append(item);
}
// 实际控制着布局,作为参数提供的矩形不包括margin()。相关的,使用spacing()作为项目之间的距离。
void QCardLayout::setGeometry(const QRect &r)
{
QLayout::setGeometry(r);
if (list.size() == 0)
return;
int w = r.width() - (list.count() - 1) * spacing();
int h = r.height() - (list.count() - 1) * spacing();
int i = 0;
while (i < list.size()) {
QLayoutItem *o = list.at(i);
QRect geom(r.x() + i * spacing(), r.y() + i * spacing(), w, h);
o->setGeometry(geom);
++i;
}
}
// sizeHint()和minimumSize()通常非常相似。这两个函数返回的尺寸应包括spacing(),但不包括margin()。
QSize QCardLayout::sizeHint() const
{
QSize s(0,0);
int n = list.count();
if (n > 0)
s = QSize(100,70);
int i = 0;
while (i < n) {
QLayoutItem *o = list.at(i);
s = s.expandedTo(o->sizeHint());
++i;
}
return s + n*QSize(spacing(), spacing());
}
QSize QCardLayout::minimumSize() const
{
QSize s(0,0);
int n = list.count();
int i = 0;
while (i < n) {
QLayoutItem *o = list.at(i);
s = s.expandedTo(o->minimumSize());
++i;
}
return s + n*QSize(spacing(), spacing());
}