1、QT自带Layout
QLayoutItem是所有布局的基类,子类的继承关系如下:
1.1、QLayout
1.1.1、QBoxLayout
盒子布局,
1.1.1.1、QHBoxLayout
水平盒子布局,所有的widget都水平方向排列;
1.1.1.2、QVBoxLayout
垂直盒子布局,所有的widget都垂直方向排列;
1.1.2、QFormLayout
表单布局,正如表单一样,行数可变,但每行都只有两列;
每行都包含一个名称/值形式,名称对应LabelWidget,值对应Edit、ComboBox等widget;
1.1.3、QGridLayout
表格布局,可以是多行多列;
1.1.4、QStackedLayout
堆布局;
1.2、QSpacerItem
1.3、QWidgetItem
2、QLayoutItem类介绍
/* 构造函数,指明对齐方式 */
QLayoutItem ( Qt::Alignment alignment = 0 )
virtual ~QLayoutItem ()
/*对齐方式 */
void setAlignment ( Qt::Alignment alignment )
Qt::Alignment alignment () const
/* 几何位置 */
virtual void setGeometry ( const QRect & r ) = 0
virtual QRect geometry () const = 0
QSizePolicy::ControlTypes controlTypes () const
virtual Qt::Orientations expandingDirections () const = 0
/* Height是否和Width关联,如果相关联,则heightForWidth指明了这种关联 */
virtual bool hasHeightForWidth () const
virtual int heightForWidth ( int w ) const
virtual void invalidate ()
/* 该Item是否为空,也就是说该Item是否包含子Widget */
virtual bool isEmpty () const = 0
/* 返回和宽度w对应的最小Height */
virtual int minimumHeightForWidth ( int w ) const
/* 返回该Item的最佳Size */
virtual QSize sizeHint () const = 0
/* 返回该Item的最大/小Size */
virtual QSize minimumSize () const = 0
virtual QSize maximumSize () const = 0
/* 如果该Item是一个QSpacerItem,则返回QSpacerItem */
/* 如果该Item是一个QWidget,则返回QWidget */
/* 如果该Item是一个LayOut,则返回QLayOut */
/* 主要在类型安全转换时使用 */
virtual QSpacerItem * spacerItem ()
virtual QLayout * layout ()
virtual QWidget * widget ()
3、QLayout类介绍
/* 向Layout添加对象 */
virtual void addItem ( QLayoutItem * item ) = 0
void addWidget ( QWidget * w )
/* 对象个数 */
virtual int count () const = 0
/* 根据Index确定对应的Widget,根据Widget确定对应的Index */
virtual int indexOf ( QWidget * widget ) const
virtual QLayoutItem * itemAt ( int index ) const = 0
/* 根据Index确定对应的Item,类似于itemAt */
virtual QLayoutItem * takeAt ( int index ) = 0
/* 告诉Geometry Manager将widget菜单条关联到Layout的parentWidget上,
例如:layout是dialog的mainlayout,则layout->setMenuBar(widget)会将widget菜单条关联到dialog上,也就是dialog的菜单条 */
QWidget * parentWidget () const
QWidget * menuBar () const
void setMenuBar ( QWidget * widget )
4、自定义Layout
自定义Layout,就是从QLayoutItem派生。
BorderLayout包括东西南北中五个方位,可以向不同方位添加元素;
头文件:
class BorderLayout : public QLayout
{
public:
/* 位置方位:东西南北中五个方位 */
enum Position { West, North, South, East, Center };
/* 构造,析构 */
BorderLayout(QWidget *parent, int margin = 0, int spacing = -1);
BorderLayout(int spacing = -1);
~BorderLayout();
/* 从QLayout类派生的方法 */
/* 添加Widget和Item */
void addItem(QLayoutItem *item);
void addWidget(QWidget *widget, Position position);
/* 扩展方向 */
Qt::Orientations expandingDirections() const;
int count() const;
QLayoutItem *itemAt(int index) const;
QLayoutItem *takeAt(int index);
/* 从QLayoutItem类派生的方法 */
bool hasHeightForWidth() const;
QSize minimumSize() const;
void setGeometry(const QRect &rect);
QSize sizeHint() const;
void add(QLayoutItem *item, Position position);
private:
struct ItemWrapper
{
/* BorderLayout布局元素:元素自身、位置信息 */
ItemWrapper(QLayoutItem *i, Position p)
{
item = i;
position = p;
}
QLayoutItem *item;
Position position;
};
enum SizeType { MinimumSize, SizeHint };
/* 根据类型,计算BorderLayout的Size */
QSize calculateSize(SizeType sizeType) const;
/* 所有的BorderLayout元素,保存在链表list中 */
QList<ItemWrapper *> list;
};
CPP文件
BorderLayout::BorderLayout(QWidget *parent, int margin, int spacing)
: QLayout(parent)
{
setMargin(margin);
setSpacing(spacing);
}
BorderLayout::BorderLayout(int spacing)
{
setSpacing(spacing);
}
/* 析构时,删除list中存在的所有widget */
BorderLayout::~BorderLayout()
{
QLayoutItem *l;
while ((l = takeAt(0)))
delete l;
}
void BorderLayout::addItem(QLayoutItem *item)
{
/* 将新item添加到list的尾部,默认方位是西部 */
add(item, West);
}
void BorderLayout::addWidget(QWidget *widget, Position position)
{
/* 将新widget添加到list的尾部 */
add(new QWidgetItem(widget), position);
}
Qt::Orientations BorderLayout::expandingDirections() const
{
/* 支持水平和垂直两个方向的扩展 */
return Qt::Horizontal | Qt::Vertical;
}
bool BorderLayout::hasHeightForWidth() const
{
/* Height和Width没有关联 */
return false;
}
int BorderLayout::count() const
{
/* 链表长度本质上就是BorderLayout的元素个数 */
return list.size();
}
/* 根据index找到相应的元素 */
QLayoutItem *BorderLayout::itemAt(int index) const
{
ItemWrapper *wrapper = list.value(index);
if (wrapper)
return wrapper->item;
else
return 0;
}
QSize BorderLayout::minimumSize() const
{
/* MinimumSize模式下的Size也就是minimumSize */
return calculateSize(MinimumSize);
}
void BorderLayout::setGeometry(const QRect &rect)
{
ItemWrapper *center = 0;
int eastWidth = 0;
int westWidth = 0;
int northHeight = 0;
int southHeight = 0;
int centerHeight = 0;
int i;
QLayout::setGeometry(rect);
for (i = 0; i < list.size(); ++i)
{
ItemWrapper *wrapper = list.at(i);
QLayoutItem *item = wrapper->item;
Position position = wrapper->position;
if (position == North)
{
item->setGeometry(QRect(rect.x(), northHeight, rect.width(),item->sizeHint().height()));
northHeight += item->geometry().height() + spacing();
}
else if (position == South)
{
item->setGeometry(QRect(item->geometry().x(),item->geometry().y(), rect.width(),item->sizeHint().height()));
southHeight += item->geometry().height() + spacing();
item->setGeometry(QRect(rect.x(),rect.y() + rect.height() - southHeight + spacing(),
item->geometry().width(),item->geometry().height()));
}
else if (position == Center)
{
center = wrapper;
}
}
centerHeight = rect.height() - northHeight - southHeight;
for (i = 0; i < list.size(); ++i)
{
ItemWrapper *wrapper = list.at(i);
QLayoutItem *item = wrapper->item;
Position position = wrapper->position;
if (position == West)
{
item->setGeometry(QRect(rect.x() + westWidth, northHeight,item->sizeHint().width(), centerHeight));
westWidth += item->geometry().width() + spacing();
}
else if (position == East)
{
item->setGeometry(QRect(item->geometry().x(), item->geometry().y(),item->sizeHint().width(), centerHeight));
eastWidth += item->geometry().width() + spacing();
item->setGeometry(QRect(rect.x() + rect.width() - eastWidth + spacing(),
northHeight, item->geometry().width(),item->geometry().height()));
}
}
if (center)
center->item->setGeometry(QRect(westWidth, northHeight,rect.width() - eastWidth - westWidth,enterHeight));
}
QSize BorderLayout::sizeHint() const
{
return calculateSize(SizeHint);
}
QLayoutItem *BorderLayout::takeAt(int index)
{
if (index >= 0 && index < list.size()) {
ItemWrapper *layoutStruct = list.takeAt(index);
return layoutStruct->item;
}
return 0;
}
void BorderLayout::add(QLayoutItem *item, Position position)
{
list.append(new ItemWrapper(item, position));
}
QSize BorderLayout::calculateSize(SizeType sizeType) const
{
QSize totalSize;
for (int i = 0; i < list.size(); ++i) {
ItemWrapper *wrapper = list.at(i);
Position position = wrapper->position;
QSize itemSize;
if (sizeType == MinimumSize)
itemSize = wrapper->item->minimumSize();
else // (sizeType == SizeHint)
itemSize = wrapper->item->sizeHint();
if (position == North || position == South || position == Center)
totalSize.rheight() += itemSize.height();
if (position == West || position == East || position == Center)
totalSize.rwidth() += itemSize.width();
}
return totalSize;
}
待补充。