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

相关推荐
秋田君16 小时前
QT_JSON文件操作
开发语言·qt·json
大白同学42117 小时前
初识Qt——信号和槽
开发语言·qt
秋田君18 小时前
QT_INI文件操作
开发语言·qt
≮傷£≯√18 小时前
FFmpeg + qt 音频播放
qt·ffmpeg·音视频
youqingyike18 小时前
【无标题】
前端·qt
程序员老陆19 小时前
Qt::WidgetAttribute 常用属性详解
开发语言·qt
程序员老陆1 天前
Qt的QThread::usleep和FFmpeg的libavutil模块的av_usleep哪个精度高一些?
开发语言·qt·ffmpeg·音视频
Quz1 天前
QML TextArea 入门(二):富文本与换行模式
qt
大白同学4212 天前
初识Qt——创建第一个Qt项目
开发语言·qt
秋田君2 天前
QT_绘图原理双缓冲机制
服务器·数据库·qt