Custom Layout Manager

Links to the original text: https://my.oschina.net/fuyajun1983cn/blog/263887

To write a custom layout manager, you need to derive from the QLayout class and define the following methods and data structures:

  • Store the data structure of each item on the layout manager, each item being a QLayout Item.

  • addItem(), which defines how to add each item to the layout manager.

  • setGeometry(), how to execute the layout.

  • sizeHint(), the size that the layout manager prefers.

  • itemAt(), how to iterate over these items in the layout manager.

  • takeAt(), how to delete these items from the layout manager.

  • In most cases, you also need to implement the minimumSize() method.

The following is an example of implementing a custom layout manager, called CardLayout.

Head file:

#ifndef CARDLAYOUT_H
#define CARDLAYOUT_H

#include <QWidget>
#include <QLayout>
#include <QList>

class CardLayout : public QLayout
{
    Q_OBJECT
public:
    explicit CardLayout(QWidget *parent = 0, int margin = 0, int dist=-1);
    ~CardLayout();

    void addItem(QLayoutItem *);
    QSize sizeHint() const;
    QSize minimumSize() const;
    int count() const;
    QLayoutItem *itemAt(int index) const;
    QLayoutItem *takeAt(int index);
    void setGeometry(const QRect &);

private:
    QList<QLayoutItem*> list;

};

#endif // CARDLAYOUT_H

Implementation document:

#include "cardlayout.h"

CardLayout::CardLayout(QWidget *parent,
                       int margin, int dist) :
    QLayout(parent)
{
    setMargin(margin);
    setSpacing(dist);
}

CardLayout::~CardLayout()
{
    QLayoutItem *item;
    while ((item = takeAt(0)))
        delete item;
}

int CardLayout::count() const
{
    // returns the number of QLayoutItems
    return list.size();
}

QLayoutItem *CardLayout::itemAt(int index) const
{
    return list.value(index);
}

QLayoutItem *CardLayout::takeAt(int index)
{
    return index >= 0 && index < list.size() ? list.takeAt(index) : 0;
}

void CardLayout::addItem(QLayoutItem *item)
{
    list.append(item);
}

void CardLayout::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;
    }
}

QSize CardLayout::sizeHint() const
{
    QSize s(0, 0);
    int n = list.count();
    if (n > 0)
        s = QSize(100, 70);//start with a nice default size
    int i = 0;
    while (i < n) {
        QLayoutItem *o = list.at(i);
        s = s.expandedTo(o->sizeHint());
        ++i;
    }
    return s + n * QSize(spacing(), spacing());
}

QSize CardLayout::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->sizeHint());
        ++i;
    }
    return s + n * QSize(spacing(), spacing());
}

Test code:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QLabel *l1 = new QLabel("label1");
    QLabel *l2 = new QLabel("label2");
    QLabel *l3 = new QLabel("label3");
    QLabel *l4 = new QLabel("label4");

    CardLayout *layout = new CardLayout;
    layout->addItem(new QWidgetItem(l1));
    layout->addItem(new QWidgetItem(l2));
    layout->addWidget(l3);
    layout->addWidget(l4);

    qDebug()<<"count: "<<layout->count();

    QWidget *central = new QWidget(this);
    central->setLayout(layout);
    setCentralWidget(central);
}



Reproduced in: https://my.oschina.net/fuyajun1983cn/blog/263887

Posted on Sat, 05 Oct 2019 22:11:47 -0700 by eazyefolife