自定义卡片布局CardLayout,这个布局是官方用来介绍怎么实现一个自定义布局的示例。
自定义布局第一步就是要继承QLayout 然而QLayout却是个抽象类,有几个纯虚函数必须要是实现下:
cpp
virtual void addItem(QLayoutItem *item) = 0
//向布局中添加控件
virtual int count() const = 0
//布局中控件数量
virtual QLayoutItem *itemAt(int index) const = 0
//根据下标获取控件
virtual QLayoutItem *takeAt(int index) = 0
//根据下标移除控件
virtual QSize sizeHint() const = 0
//默认大小
这些还都只是对布局中子控件管理的功能,真正处理控件布局位置的函数却是:
cpp
virtual void setGeometry(const QRect&) = 0
CardLayout 实现
接下来进入主题,看下这些函数都是怎么实现的,类定义:
cpp
class CardLayout : public QLayout
{
Q_OBJECT
public:
CardLayout(QWidget *parent = nullptr);
~CardLayout();
void addItem(QLayoutItem *item) override;
int count() const override;
QLayoutItem *itemAt(int) const override;
QLayoutItem *takeAt(int) override;
QSize sizeHint() const override;
void setGeometry(const QRect &rect) override;
private:
QList<QLayoutItem*> list;
};
对于子控件的管理用的是QList<QLayoutItem*>,简单直接。
成员函数实现:
cpp
CardLayout::CardLayout(QWidget *parent):
QLayout(parent)
{}
CardLayout::~CardLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}
void CardLayout::addItem(QLayoutItem *item)
{
list.append(item);
}
int CardLayout::count() const
{
return list.count();
}
QLayoutItem *CardLayout::itemAt(int idx) const
{
return list.value(idx);
}
QLayoutItem *CardLayout::takeAt(int idx)
{
return idx >= 0 && idx < list.size() ? list.takeAt(idx) : 0;
}
QSize CardLayout::sizeHint() const
{
return QSize(0,0);
}
void CardLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
if(list.size() == 0)
return;
int w = rect.width() - (list.count() - 1)*spacing();
int h = rect.height() - (list.count() - 1)* spacing();
int i = 0;
while (i < list.size())
{
QLayoutItem *o = list.at(i);
QRect geom(rect.x() + i*spacing(), rect.y() + i*spacing(), w, h);
o->setGeometry(geom);
++i;
}
}
sizeHint这里是直接给0,暂且也不需要它发挥作用。
看过setGeometry的实现后,这个自定义的卡片布局的就很清晰了,每个子控件就是向右下角依次做个偏移显示而已。
调用示例
cpp
CardLayout * lay = new CardLayout;
for(int i=0; i<5; i++)
{
lay->addItem(
new QWidgetItem(new QPushButton(QString::number(i+1)))
);
}
this->setLayout(lay);
弄了5个按钮来试试这新实现的卡片布局。看下效果:
