CardLayout 实现自定义布局

自定义卡片布局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个按钮来试试这新实现的卡片布局。看下效果:

相关推荐
郝学胜_神的一滴9 小时前
Qt 高级开发 031:QListWidget图标布局实战
c++·qt
Vertira10 小时前
如何对QT开发的软件进行打包[已解决]
开发语言·qt
大智兄10 小时前
128.配置qt(交叉)编译的路径---解决无法编译的问题
qt
Henry Zhu12315 小时前
Qt 元对象系统源码级理解
qt
读书札记202216 小时前
Qt中windeployqt.exe工具的使用:解决使用CMake创建的项目点击exe文件后系统提示0xc000007b的问题
开发语言·qt
luoyayun36117 小时前
Qt + FFmpeg 实战:实现音频格式转换功能
qt·ffmpeg·音频格式转换
Henry Zhu12317 小时前
Qt 信号槽、事件循环与线程通信源码级理解
开发语言·qt
郝学胜-神的一滴17 小时前
CMake 015:日志级别全解析
linux·开发语言·c++·qt·程序人生·软件构建·cmake
数据法师1 天前
QuickSay :基于 Qt 的轻量级快捷短语管理工具
开发语言·qt
小短腿的代码世界1 天前
行情快照与增量更新引擎:Qt在高频交易数据分发中的核心架构——你的行情推送为什么延迟了500ms?
开发语言·qt·架构