要编写自定义布局管理器,需要从QLayout类派生,并定义如下一些方法和数据结构:
存储布局管理器上每个项的数据结构,每个项是一个QLayoutItem。
addItem(),定义怎样将每个项添加到布局管理器上。
setGeometry(),怎样执行布局。
sizeHint(),布局管理器优先选择的大小。
itemAt(),怎样在布局管理器中抚今迭代这些项。
takeAt(),怎样从布局管理器中删除这些项。
在大部分情况下,还需要实现minimumSize()方法。
下面是一个实现自定义布局管理器的实例, 称为CardLayout。
头文件:
#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
#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()); }
测试代码:
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); }