一、简介
本文基于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_OBJECT
public:
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_OBJECT
public:
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" };
// 添加label
setLabelInfo();
// 设置选中状态
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_OBJECT
public:
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()
{
}