一、简介
本文基于QGroupBox扩展了一种可以伸缩的组合框,正常状态下,组合框处于收缩状态,内部的控件是隐藏的;需要的时候,可以将组合框进行伸展,并将内部控件显示出来。
二、主要思路
实现的代码比较简单,主要有以下几点:
1、该组合框继承于QGroupBox;
2、将QGroupBox的可选择属性setCheckable设置为true
3、通过QGroupBox的setFlat函数显示隐藏垂直边框
4、根据QGroupBox的点击事件判断其展开还是收缩
5、右侧的展开或缩放的样式是一个Label,通过设置相对布局实现,“+”“-”均为字符串;边框是使用QSS样式
三、显示效果
四、代码
extendedgroupbox.h
#ifndef EXTENDEDGROUPBOX_H#define EXTENDEDGROUPBOX_H#include <QGroupBox>#include <QLabel>#include <QMouseEvent>#include <QWidget>class QClickableLabel;class ExtendedGroupBox : public QGroupBox {Q_OBJECTpublic:enum State {STATE_NORMAL,STATE_EXPAND};ExtendedGroupBox(QWidget* parent = nullptr, State state = STATE_EXPAND);ExtendedGroupBox(const QString& title, QWidget* parent = nullptr,State state = STATE_EXPAND);private:void init(State state);void setLabelInfo();void slotOnChecked();void hidenWidget(bool isVisible);void setLabelGeometry(QSize size);protected:void resizeEvent(QResizeEvent* event) override;public:State getState() const;private:QClickableLabel* clickedLabel;// 存放要隐藏的控件的名称(通过 QWidget->metaObject()->className())QList<QString> hideWidgets_;// 点击状态State state_;};// QLabel增加点击事件class QClickableLabel : public QLabel {Q_OBJECTpublic:using QLabel::QLabel;~QClickableLabel() { }signals:void clicked();protected:void mousePressEvent(QMouseEvent* ev) override{if (ev->button() == Qt::LeftButton) {emit clicked();}}};#endif // EXTENDEDGROUPBOX_H
extendedgroupbox.cpp
#include "extendedgroupbox.h"#include <QDebug>#include <QLabel>#include <QLayout>ExtendedGroupBox::ExtendedGroupBox(QWidget* parent, State state): QGroupBox(parent){init(state);}ExtendedGroupBox::ExtendedGroupBox(const QString& title, QWidget* parent, State state): QGroupBox(title, parent){init(state);}// 初始化void ExtendedGroupBox::init(State state){state_ = state;hideWidgets_ = { "QLabel", "QLineEdit", "QComboBox", "QGroupBox", "ExtendedGroupBox" };// 添加labelsetLabelInfo();// 设置选中状态this->setCheckable(true);if (state_ == STATE_NORMAL) {this->setFlat(true);this->setChecked(false);clickedLabel->setText("-");} else {this->setFlat(false);this->setChecked(true);clickedLabel->setText("+");}connect(clickedLabel, &QClickableLabel::clicked, this, &ExtendedGroupBox::slotOnChecked);connect(this, &ExtendedGroupBox::clicked, this, &ExtendedGroupBox::slotOnChecked);}// 设置label的信息void ExtendedGroupBox::setLabelInfo(){clickedLabel = new QClickableLabel(this);clickedLabel->setFixedSize(13, 13);clickedLabel->setStyleSheet("border:1px solid black");clickedLabel->setAlignment(Qt::AlignHCenter);setLabelGeometry(this->size());QFont font;font.setWeight(13);clickedLabel->setFont(font);}// 根据点击状态显示隐藏QGroupBox的控件void ExtendedGroupBox::slotOnChecked(){bool checked = state_ == STATE_NORMAL;if (checked) {//显示垂直边框this->setFlat(false);clickedLabel->setText("+");hidenWidget(true);state_ = STATE_EXPAND;} else {//隐藏垂直边框this->setFlat(true);clickedLabel->setText("-");hidenWidget(false);state_ = STATE_NORMAL;}}// 显示或隐藏QGroupBox里的控件void ExtendedGroupBox::hidenWidget(bool isVisible){for (QObject* child : this->children()) {QWidget* widget = static_cast<QWidget*>(child);QString className = widget->metaObject()->className();if (widget != nullptr && hideWidgets_.contains(className)) {widget->setVisible(isVisible);}}}// 设置label的位置void ExtendedGroupBox::setLabelGeometry(QSize size){int width = size.width() - 30;clickedLabel->setGeometry(width, 0, 13, 13);}// 窗口大小改变时更新label的位置void ExtendedGroupBox::resizeEvent(QResizeEvent*){setLabelGeometry(this->size());}// 返回展开状态ExtendedGroupBox::State ExtendedGroupBox::getState() const{return state_;}
widget.h
#ifndef WIDGET_H#define WIDGET_H#include <QWidget>class ExtendedGroupBox;class Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget* parent = nullptr);~Widget();private:ExtendedGroupBox* groupBox;};#endif // WIDGET_H
widget.cpp
#include "widget.h"#include "extendedgroupbox.h"#include <QFormLayout>#include <QGroupBox>#include <QLayout>#include <QLineEdit>Widget::Widget(QWidget* parent): QWidget(parent){this->resize(350, 200);this->setWindowTitle("A collapsible GroupBox");QVBoxLayout* mainLayout = new QVBoxLayout(this);this->setLayout(mainLayout);groupBox = new ExtendedGroupBox("title", parent);mainLayout->addWidget(groupBox);QFormLayout* groupLayout = new QFormLayout(groupBox);groupBox->setLayout(groupLayout);QLabel* label1 = new QLabel("group1", groupBox);QLineEdit* lineEdit1 = new QLineEdit(groupBox);QLabel* label2 = new QLabel("group2", groupBox);QLineEdit* lineEdit2 = new QLineEdit(groupBox);groupLayout->addRow(label1, lineEdit1);groupLayout->addRow(label2, lineEdit2);}Widget::~Widget(){}


