QT自定义Layout畸形布局

关于QT的自定义布局

自定义的布局形状如下

在这里插入图片描述

简介

  以前觉得自定义布局很难,但是亲手写了一下发现也很简单。就是继承子类化Layout。实现几个虚函数,然后再setGeometry()这个函数中计算各个子item的位置从而实现布局效果就好了。

实现

   通过继承QLayout这个类来实现自己的layout,QT框架中自己实现了这几个布局类可以使用:QBoxLayout, QGridLayout, QFormLayout, QStackedLayout。以及BorderLayout和flowLayout(文档详细说明)

  如果我们子类化QLayout必须实现 addItem(), sizeHint(), itemAt(), setGeometry(), takeAt()这几个函数。还应该实现mininumSize()这个函数,来确保布局的最小大小不为0。确定布局的函数主要是setGeometry(),通过计算每个子Item的位置来做成你想要的样子。

代码如下:

border.h

#include <QLayout>
#include <QList>
#include <QRect>

class Flayout : public QLayout
{
public:
    enum direction{
        TOP = 0,
        BOTTOM,
        LEFT,
        RIGHT,
        CENTER
    };

    typedef struct fitem{
        fitem(QLayoutItem *item, direction direct):
            layout_item(item),
            dir(direct){}
        QLayoutItem *layout_item;
        direction dir;
    }Fitem;

    explicit Flayout(QWidget *parent = 0);
    ~Flayout();

    void addWidget(QWidget *, direction);
    void add(QLayoutItem *, direction);

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

private:
    QList<Fitem *>m_item_list;
};

border.cc

Flayout::Flayout(QWidget *parent):
    QLayout(parent)
{
    setSpacing(0);
}

Flayout::~Flayout()
{
    QLayoutItem *l;
    while ((l = takeAt(0)))
        delete l;
}

void Flayout::addItem(QLayoutItem * item)
{
    add(item, TOP);
}

void Flayout::setGeometry(const QRect & rect)
{
    int left_height = 0;
    int left_width = 0;
    QLayout::setGeometry(rect);

    for (int i = 0; i < m_item_list.size(); ++i)
    {
        Fitem *wrapper = m_item_list.at(i);
        QLayoutItem *item = wrapper->layout_item;
        direction direct = wrapper->dir;

        if (direct == LEFT)
        {
            item->setGeometry(QRect(rect.x(), rect.y(), rect.width() / 4, rect.height() / 4 * 3));

            left_height += item->geometry().height();
            left_width  += item->geometry().width();
        }
    }

    for (int i = 0; i < m_item_list.size(); ++i)
    {
        Fitem *wrapper = m_item_list.at(i);
        QLayoutItem *item = wrapper->layout_item;
        direction position = wrapper->dir;

        if (position == TOP)
        {
            item->setGeometry(QRect(rect.x() + left_width, rect.y(),
                                    rect.width() / 4 * 3, rect.height() / 4));
        }
        else if (position == BOTTOM)
        {
            item->setGeometry(QRect(rect.x(), left_height + rect.y(),
                                    rect.width() / 4 * 3, rect.height() / 4));
        }
        else if(position == RIGHT)
        {
            item->setGeometry(QRect(rect.x() + rect.width() -  left_width ,  rect.y() + rect.height() - left_height,
                                   rect.width() / 4, rect.height() / 4 * 3));
        }
        else if(position == CENTER)
        {
            item->setGeometry(QRect(rect.x() + rect.width() / 4,  rect.y() + rect.height() / 4,
                                   rect.width() / 2, rect.height() / 2));
        }
    }
}

QSize Flayout::sizeHint() const
{
    return QSize(300, 300);
}

QLayoutItem *Flayout::itemAt(int index) const
{
    Fitem *item = m_item_list.value(index);
    if (item)
    {
        return item->layout_item;
    }
    else
    {
        return 0;
    }
}

QLayoutItem *Flayout::takeAt(int index)
{
    if (index >= 0 && index < m_item_list.size()) {
        Fitem *layoutStruct = m_item_list.takeAt(index);
        return layoutStruct->layout_item;
    }
    return 0;
}

int Flayout::count() const
{
    return m_item_list.count();
}

QSize Flayout::minimumSize() const
{
    return QSize(30,30);
}

void Flayout::addWidget(QWidget * widget, direction dir)
{
    add(new QWidgetItem(widget), dir);
}

void Flayout::add(QLayoutItem * item, direction dir)
{
    m_item_list.append(new Fitem(item, dir));
}

使用:
widget.cc:

    Flayout *pLayout = new Flayout(this);
    pLayout->addWidget(createWidget("Black"), Flayout::CENTER);
    pLayout->addWidget(createWidget("White"), Flayout::TOP);
    pLayout->addWidget(createWidget("Red"), Flayout::BOTTOM);
    pLayout->addWidget(createWidget("Green"), Flayout::LEFT);
    pLayout->addWidget(createWidget("Yellow") , Flayout::RIGHT);
    setLayout(pLayout);
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Qt中的VerticalLayout布局是一种垂直方向的布局方式,它可以将控件按照从上到下的顺序依次排列。在VerticalLayout布局中,每个控件都会占据一定的高度,并且宽度会自动适应布局的宽度。VerticalLayout布局可以通过添加控件、设置控件的大小和位置等方式来实现。它是Qt中常用的布局方式之一,可以用于创建各种不同的界面布局。 ### 回答2: Qt 中的 QVBoxLayout 是一种垂直布局,可以将子控件以垂直方向排布。 使用 QVBoxLayout,我们可以轻松地将控件垂直排列,并且不需要手动设置位置和大小。只需要将子控件添加到 QVBoxLayout 中,即可实现垂直排布。 在使用 QVBoxLayout 时,我们需要注意以下几点: 1. 可以使用 addWidget() 和 addLayout() 方法向 QVBoxLayout 中添加控件,这些控件会按照添加的顺序依次排列。 2. 可以使用 setSpacing() 方法设置子控件之间的间距,这样可以使布局更加美观。 3. 如果子控件太多,可能会导致布局溢出,此时可以将 QVBoxLayout 嵌套在 QScrollArea 中,使用户可以滚动查看所有子控件。 4. 在使用 QVBoxLayout 时,还需要注意子控件的大小。如果某个子控件的大小发生变化,可能会导致整个布局失衡,此时可以使用 setStretchFactor() 方法来为子控件设置伸展因子,从而保持布局的平衡。 总的来说,VBoxLaout 是一种非常方便实用的垂直布局方式,在设计 GUI 界面时可以大大简化布局操作。 ### 回答3: QT中的Vertical Layout布局(垂直布局)是一种方便的布局方式,可以使您的窗口中的控件沿垂直方向自动排列。它适用于需要排列多个控件的窗口,如窗口表单、选项卡等。该布局管理器可以自动控制插入新控件并自动重新设计大小。 使用Vertical Layout布局管理器时,要将输入控件从顶部开始添加,然后下一个控件将添加到第一个控件下方,以此类推。与水平布局不同,垂直布局的控件高度是相同的,但宽度可以是不同的。通过垂直布局,我们可以使多个控件在不同层次上排列,并调整控件之间的间隔,并使其垂直对齐,达到更好的视觉效果。 使用Qt Designer可以轻松创建Vertical Layout布局,只需从Qt Designer的设计面板中选择Vertical Layout,并将其拖放到界面上。可以在Vertical Layout上添加其他控件,并容易地更改每个控件的选项,如大小、间距、对齐等。此外,QT还提供了其他布局管理器,如水平布局(Horizontal Layout)、网格布局(Grid Layout)和对话框布局(Dialog Layout)等,以满足不同UI设计的需要。 总之,在开发QT应用程序时,Vertical Layout布局是一种非常方便的布局方式,可以帮助我们更快速地设计并开发出优秀的用户界面,以提高用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值