布局类(102):【例】Border Layout Example [官翻]

Border Layout Example

演示如何沿边框排列子小部件。

BorderLayout实现了一种布局,它将子窗口小部件安排在主区域周围。

main.cpp

#include <QApplication>

#include "window.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    Window window;
    window.show();
    return app.exec();
}

Window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QWidget>

QT_BEGIN_NAMESPACE
class QLabel;
QT_END_NAMESPACE

class Window : public QWidget
{
    Q_OBJECT

public:
    Window();

private:
    QWidget *createWidget(const QString &text);
};

#endif // WINDOW_H

Window.cpp

#include "borderlayout.h"
#include "window.h"
#include <QTextBrowser>
#include <QLabel>
#include <QPushButton>

/*Window类的构造函数创建一个QTextBrowser对象,其中添加了一个名为layout的BorderLayout。
 * BorderLayout类的声明在本文末尾引用。*/
Window::Window()
{
    QTextEdit *centralWidget = new QTextEdit;
    centralWidget->setPlainText(tr("Central widget"));

    BorderLayout *layout = new BorderLayout;
    // 几个带标签的小部件被添加到布局中,方向为:中心、北、西、东1、东2和南。
    layout->addWidget(centralWidget, BorderLayout::Center);
    layout->addWidget(createWidget("North1"), BorderLayout::North);
    layout->addWidget(createWidget("North2"), BorderLayout::North);
    layout->addWidget(createWidget("West1"), BorderLayout::West);
    layout->addWidget(createWidget("West2"), BorderLayout::West);
    layout->addWidget(createWidget("East 1"), BorderLayout::East);
    layout->addWidget(createWidget("East 2") , BorderLayout::East);
    layout->addWidget(createWidget("South1"), BorderLayout::South);
    layout->addWidget(createWidget("South2"), BorderLayout::South);

    layout->setMargin (15);
    layout->setSpacing (3);

    setLayout(layout);

    setWindowTitle(tr("Border Layout"));
}

/* 类窗口中的createLabel() 设置标记小部件的文本和样式。*/
QWidget *Window::createWidget(const QString &text)
{
    auto *widget = new QLabel(text);
    widget->setFrameStyle(QFrame::Panel | QFrame::Plain);
    widget->setAlignment (Qt::AlignCenter);
    return widget;
}

BorderLayout.h

#ifndef BORDERLAYOUT_H
#define BORDERLAYOUT_H

#include <QLayout>
#include <QRect>
/*
  类BorderLayout包含格式化它包含的小部件的所有实用函数。
*/
class BorderLayout : public QLayout
{
public:
    enum Position { West, North, South, East, Center };

    explicit BorderLayout(QWidget *parent, const QMargins &margins = QMargins(), int spacing = -1);
    BorderLayout(int spacing = -1);
    ~BorderLayout();

    void addItem(QLayoutItem */*item*/) override{};          //[pure virtual]
    int count() const override;                                     //[pure virtual]
    QLayoutItem *takeAt(int index) override;              //[pure virtual]
    QLayoutItem *itemAt(int index) const override;     //[pure virtual]

    void addWidget(QWidget *widget, Position position);
    void add(QLayoutItem *item, Position position);


//    Qt::Orientations expandingDirections() const override;
//    bool hasHeightForWidth() const override;
    QSize minimumSize() const override;
    void setGeometry(const QRect &rect) override;
    QSize sizeHint() const override;


private:
    struct ItemWrapper
    {
        ItemWrapper(QLayoutItem *i, Position p) {
            item = i;
            position = p;
        }

        QLayoutItem *item;
        Position position;
    };

    enum SizeType { MinimumSize, SizeHint };

    QSize calculateSize(SizeType sizeType) const;

    QList<ItemWrapper *> list;   // 使用list管理布局的项目
};

#endif // BORDERLAYOUT_H

BorderLayout.cpp

#include "borderlayout.h"

BorderLayout::BorderLayout(QWidget *parent, const QMargins &margins, int spacing)
    : QLayout(parent)
{
    setContentsMargins(margins);       // 设置页边距
    setSpacing(spacing);                     // 设置间隔
}

BorderLayout::BorderLayout(int spacing)
{
    setSpacing(spacing);           // 设置间隔
}


BorderLayout::~BorderLayout()
{
    QLayoutItem *l;
    while ((l = takeAt(0)))
        delete l;
}
/* 增加项目 没有用到      [pure virtual] */
//void BorderLayout::addItem(QLayoutItem */*item*/)
//{}

/* 加入项目管理器list  */
void BorderLayout::addWidget(QWidget *widget, Position position)
{
    add(new QWidgetItem(widget), position);      // 加入项目管理器list
}

/* 设置可扩展方向    */
//Qt::Orientations BorderLayout::expandingDirections() const
//{
//    return Qt::Horizontal | Qt::Vertical;        // 水平方向和垂直方向都可扩展
//}


/* 布局的首选高度是否取决于其宽度  */
//bool BorderLayout::hasHeightForWidth() const
//{
//    return false;                //  默认false
//}

/* 返回布局项目的总数量               [pure virtual]   */
int BorderLayout::count() const
{
    return list.size();
}

/* 根据索引返回布局项目指针           [pure virtual]   */
QLayoutItem *BorderLayout::itemAt(int index) const
{
    ItemWrapper *wrapper = list.value(index);
    return wrapper ? wrapper->item : nullptr;
}

 /*返回最小尺寸 */
QSize BorderLayout::minimumSize() const
{
    return calculateSize(MinimumSize);
}

void BorderLayout::setGeometry(const QRect &rect)
{
    ItemWrapper *center = nullptr;
    int eastWidth = 0;
    int westWidth = 0;
    int northHeight = 0;
    int southHeight = 0;
    int centerHeight = 0;
    int i;
    QLayout::setGeometry(rect);

    QRect rect0 = rect.adjusted (contentsMargins ().left (),contentsMargins ().top (),
                                 -contentsMargins ().right (),-contentsMargins ().bottom ());

    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(rect0.x (), rect0.y () + northHeight,
                                    rect0.width(),
                                    item->sizeHint().height()));
            northHeight += item->geometry().height() + spacing();
        }
        else if (position == South) {
            item->setGeometry(QRect(item->geometry().x(),
                                    item->geometry().y(),
                                    rect0.width(),
                                    item->sizeHint().height()));

            southHeight += item->geometry().height() + spacing();

            item->setGeometry(QRect(rect0.x(),
                                    rect0.y() + rect0.height() - southHeight + spacing(),
                                    item->geometry().width(),
                                    item->geometry().height()));
        } else if (position == Center) {
            center = wrapper;
        }
    }

    centerHeight = rect0.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(
                                   rect0.x() + westWidth,
                                   rect0.y () + 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(
                                  rect0.x() + rect0.width() - eastWidth + spacing(),
                                  rect0.y()+northHeight,
                                  item->geometry().width(),
                                  item->geometry().height()));
        }
    }

    if (center)
        center->item->setGeometry(QRect(
                                      rect0.x ()+westWidth,
                                      rect0.y ()+northHeight+1,
                                      rect0.width() - eastWidth - westWidth,
                                      centerHeight - 1));
}

QSize BorderLayout::sizeHint() const
{
    return calculateSize(SizeHint);
}

//  按索引移除项目            [pure virtual]
QLayoutItem *BorderLayout::takeAt(int index)
{
    if (index >= 0 && index < list.size()) {
        ItemWrapper *layoutStruct = list.takeAt(index);
        return layoutStruct->item;
    }
    return nullptr;
}

// 添加项目
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();
    }
    totalSize.rwidth  () += contentsMargins ().left () + contentsMargins ().right     ();
    totalSize.rheight () += contentsMargins ().top () + contentsMargins ().bottom ();
    return totalSize;
}

总结

边界布局,自己写写挺好玩的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值