Qt类似于网格布局的窗口容器QBoxWidget简介

3 篇文章 0 订阅
2 篇文章 0 订阅

一. 概述

    Qt的基本布局有水平布局(QHBoxLayout)、垂直布局(QVBoxLayout)、网格布局(QGridLayout)、表单布局(QFormLayout)等。QBoxWidget作为一个类似网格布局的窗口容器,将加入到容器中的窗口按照网格布局方式排列,根据窗口的数量自动计算行数与列数。与网格布局的不同之处在于,网格布局中的某个单元格中的窗口暂时隐藏之后,空余出来的空间不会被同一行的其他窗口延伸利用,QBoxWidget实现了某个网格暂时隐藏之后,同一行的其他窗口会重新分配横向上占用的空间,自动延伸,从而实现尽可能占用更多空间的功能。

二. 运行效果图

1. 所有窗口均显示的情形

2. 某些窗口暂时隐藏时的情形

3. 某个窗口最大化显示情形

三. 实现基本原理

    根据容器中窗口的个数,先计算一行应该有多少列(nCol)“int nCol = 0.9999 + sqrt(m_vWidget.size());”,再计算应该有多少行nRow“int nRow = (m_vWidget.size() + nCol - 1) / nCol;”,然后创建nRow个水平布局(QHBoxLayout)容器,每个nCol水平布局(QHBoxLayout)容器中加入最多nCol个窗口,最后将这些水平布局(QHBoxLayout)容器加入到垂直布局(QVBoxLayout)容器中。

四. qboxwidget.h代码

#ifndef QBOXWIDGET_H

#define QBOXWIDGET_H

 

#include <QWidget>

#include <QVBoxLayout>

#include <vector>

 

 

class QPushButton;

 

class QCellWidget : public QWidget

{

Q_OBJECT

public:

explicit QCellWidget(QWidget *widget, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());

 

enum ShowType

{

ST_HIDE,

ST_MAXIMIZED

};

 

protected:

virtual void resizeEvent(QResizeEvent *event);

virtual void paintEvent(QPaintEvent *event) override;

 

signals:

void showCell(int);

 

private slots :

void ShowCell();

 

private:

QPushButton *m_pBtnHide;

QPushButton *m_pBtnMaximize;

QVBoxLayout m_LayoutV;

};

 

class QBoxWidget : public QWidget

{

    Q_OBJECT

public:

    explicit QBoxWidget(QWidget *parent = nullptr, int nMaxCol = 0);

 

    void AddWidget(QWidget *pWidget, bool bDoLayout = false);

    void DoLayout();

int FindWidget(QWidget *pWidget);

inline const QVBoxLayout& GetLayout() const { return m_LayoutV; };

inline void MaximizeWidget(QWidget *pWidget = NULL) { MaximizeWidget2(FindWidget(pWidget)); };

inline void HideWidget(QWidget *pWidget = NULL) { HideWidget2(FindWidget(pWidget)); };

inline void ShowWidget(QWidget *pWidget = NULL) { ShowWidget2(FindWidget(pWidget)); };

void MaximizeWidget2(int nIndex = -1);

void HideWidget2(int nIndex = -1);

void ShowWidget2(int nIndex = -1);

 

private:

 

signals:

 

public slots :

void ShowCell(int);

 

private:

int m_nMaxCol;

    QVBoxLayout                 m_LayoutV;

    std::vector<QWidget*>       m_vWidget;

};

 

#endif // QBOXWIDGET_H

 

五. qboxwidget.cpp代码

#include "qboxwidget.h"

#include <math.h>

 

#include <QPainter>

#include <QPushButton>

#include <QMouseEvent>

 

QCellWidget::QCellWidget(QWidget *widget, QWidget *parent, Qt::WindowFlags f)

: QWidget(parent, f), m_LayoutV(this)

{

widget->setParent(parentWidget());

m_LayoutV.setMargin(0);

m_LayoutV.addWidget(widget);

 

QPixmap pix;

pix.load("max.png");

QIcon icon(pix);

m_pBtnMaximize = new QPushButton(icon, "", this);

m_pBtnMaximize->setFlat(true);

m_pBtnMaximize->setStyleSheet("margin:0px");

m_pBtnMaximize->setFixedSize(13, 13);

m_pBtnHide = new QPushButton(QStringLiteral("×"), this);

m_pBtnHide->setFlat(true);

m_pBtnHide->setStyleSheet("margin:0px;color: rgb(160, 160, 160);");

m_pBtnHide->setFixedSize(12, 12);

connect(m_pBtnMaximize, SIGNAL(clicked()), this, SLOT(ShowCell()));

  connect(m_pBtnHide, SIGNAL(clicked()), this, SLOT(ShowCell()));

}

 

void QCellWidget::resizeEvent(QResizeEvent *event)

{

QRect rc = rect();

m_pBtnHide->move(rc.right() - 12, 1);

m_pBtnMaximize->move(rc.right() - 28, 0);

}

 

void QCellWidget::paintEvent(QPaintEvent *event)

{

QRect rc = rect();

QPainter p(this);

p.setPen(QColor(224, 224, 224));

p.drawRect(rc.left(), rc.top(), rc.width() - 1, rc.height() - 1);

}

 

void QCellWidget::ShowCell()

{

if (sender() == m_pBtnMaximize)

{

emit showCell(ST_MAXIMIZED);

}

else

{

emit showCell(ST_HIDE);

}

}

 

QBoxWidget::QBoxWidget(QWidget *parent, int nMaxCol) : QWidget(parent), m_LayoutV(this)//此处必须加this

{

m_nMaxCol = nMaxCol;

m_LayoutV.setMargin(0);

m_LayoutV.setSpacing(1);

}

 

void QBoxWidget::AddWidget(QWidget *pWidget, bool bDoLayout)

{

    if(pWidget != NULL)

    {

//pWidget->setParent(parentWidget());

QCellWidget *pCW = new QCellWidget(pWidget, parentWidget());

connect(pCW, SIGNAL(showCell(int)), this, SLOT(ShowCell(int)));

        m_vWidget.push_back(pCW);

    }

 

    if(bDoLayout)

    {

        DoLayout();

    }

}

 

void QBoxWidget::DoLayout()

{

int nCol = 0.9999 + sqrt(m_vWidget.size());

if (m_nMaxCol > 0 && nCol > m_nMaxCol)

{

nCol = m_nMaxCol;

}

int nRow = (m_vWidget.size() + nCol - 1) / nCol;

 

while (m_LayoutV.count())

{

delete m_LayoutV.takeAt(0);

}

 

for (int i = 0; i < nRow; i++)

{

QHBoxLayout *pLayout = new QHBoxLayout();//this);//此处可以不加this

for (int j = 0; j < nCol; j++)

{

int nIndex = i*nCol + j;

if (nIndex < m_vWidget.size())

{

pLayout->addWidget(m_vWidget[nIndex]);

}

}

pLayout->setMargin(0);

pLayout->setSpacing(1);

m_LayoutV.addItem(pLayout);

}

}

 

int QBoxWidget::FindWidget(QWidget *pWidget)

{

if (pWidget != NULL)

{

for (int i = m_vWidget.size() - 1; i >= 0; i--)

{

if (m_vWidget[i] == pWidget)

{

return i;

}

}

}

return -1;

}

 

void QBoxWidget::MaximizeWidget2(int nIndex /*= -1*/)

{

int i;

if (nIndex < 0 || nIndex >= m_vWidget.size())

{

for (i = m_vWidget.size() - 1; i >= 0; i--)

{

m_vWidget[i]->show();

}

}

else

{

for (i = m_vWidget.size() - 1; i >= 0; i--)

{

m_vWidget[i]->setVisible(i == nIndex);

}

}

m_LayoutV.update();

}

 

void QBoxWidget::HideWidget2(int nIndex /*= -1*/)

{

if (nIndex >= 0 && nIndex < m_vWidget.size())

{

m_vWidget[nIndex]->hide();

m_LayoutV.update();

}

}

 

void QBoxWidget::ShowWidget2(int nIndex /*= -1*/)

{

if (nIndex >= 0 && nIndex < m_vWidget.size())

{

m_vWidget[nIndex]->show();

m_LayoutV.update();

}

}

 

void QBoxWidget::ShowCell(int nType)

{

QWidget *pWidget = (QWidget*)sender();

if (nType == QCellWidget::ST_MAXIMIZED)

{

MaximizeWidget(pWidget);

}

else if (nType == QCellWidget::ST_HIDE)

{

HideWidget(pWidget);

}

}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值