一、简介

本文基于QGroupBox扩展了一种可以伸缩的组合框,正常状态下,组合框处于收缩状态,内部的控件是隐藏的;需要的时候,可以将组合框进行伸展,并将内部控件显示出来。

二、主要思路

实现的代码比较简单,主要有以下几点:
1、该组合框继承于QGroupBox;

2、将QGroupBox的可选择属性setCheckable设置为true

3、通过QGroupBox的setFlat函数显示隐藏垂直边框

4、根据QGroupBox的点击事件判断其展开还是收缩

5、右侧的展开或缩放的样式是一个Label,通过设置相对布局实现,“+”“-”均为字符串;边框是使用QSS样式

三、显示效果

image.pngimage.png
image.png

四、代码

extendedgroupbox.h

  1. #ifndef EXTENDEDGROUPBOX_H
  2. #define EXTENDEDGROUPBOX_H
  3. #include <QGroupBox>
  4. #include <QLabel>
  5. #include <QMouseEvent>
  6. #include <QWidget>
  7. class QClickableLabel;
  8. class ExtendedGroupBox : public QGroupBox {
  9. Q_OBJECT
  10. public:
  11. enum State {
  12. STATE_NORMAL,
  13. STATE_EXPAND
  14. };
  15. ExtendedGroupBox(QWidget* parent = nullptr, State state = STATE_EXPAND);
  16. ExtendedGroupBox(const QString& title, QWidget* parent = nullptr,
  17. State state = STATE_EXPAND);
  18. private:
  19. void init(State state);
  20. void setLabelInfo();
  21. void slotOnChecked();
  22. void hidenWidget(bool isVisible);
  23. void setLabelGeometry(QSize size);
  24. protected:
  25. void resizeEvent(QResizeEvent* event) override;
  26. public:
  27. State getState() const;
  28. private:
  29. QClickableLabel* clickedLabel;
  30. // 存放要隐藏的控件的名称(通过 QWidget->metaObject()->className())
  31. QList<QString> hideWidgets_;
  32. // 点击状态
  33. State state_;
  34. };
  35. // QLabel增加点击事件
  36. class QClickableLabel : public QLabel {
  37. Q_OBJECT
  38. public:
  39. using QLabel::QLabel;
  40. ~QClickableLabel() { }
  41. signals:
  42. void clicked();
  43. protected:
  44. void mousePressEvent(QMouseEvent* ev) override
  45. {
  46. if (ev->button() == Qt::LeftButton) {
  47. emit clicked();
  48. }
  49. }
  50. };
  51. #endif // EXTENDEDGROUPBOX_H

extendedgroupbox.cpp

  1. #include "extendedgroupbox.h"
  2. #include <QDebug>
  3. #include <QLabel>
  4. #include <QLayout>
  5. ExtendedGroupBox::ExtendedGroupBox(QWidget* parent, State state)
  6. : QGroupBox(parent)
  7. {
  8. init(state);
  9. }
  10. ExtendedGroupBox::ExtendedGroupBox(const QString& title, QWidget* parent, State state)
  11. : QGroupBox(title, parent)
  12. {
  13. init(state);
  14. }
  15. // 初始化
  16. void ExtendedGroupBox::init(State state)
  17. {
  18. state_ = state;
  19. hideWidgets_ = { "QLabel", "QLineEdit", "QComboBox", "QGroupBox", "ExtendedGroupBox" };
  20. // 添加label
  21. setLabelInfo();
  22. // 设置选中状态
  23. this->setCheckable(true);
  24. if (state_ == STATE_NORMAL) {
  25. this->setFlat(true);
  26. this->setChecked(false);
  27. clickedLabel->setText("-");
  28. } else {
  29. this->setFlat(false);
  30. this->setChecked(true);
  31. clickedLabel->setText("+");
  32. }
  33. connect(clickedLabel, &QClickableLabel::clicked, this, &ExtendedGroupBox::slotOnChecked);
  34. connect(this, &ExtendedGroupBox::clicked, this, &ExtendedGroupBox::slotOnChecked);
  35. }
  36. // 设置label的信息
  37. void ExtendedGroupBox::setLabelInfo()
  38. {
  39. clickedLabel = new QClickableLabel(this);
  40. clickedLabel->setFixedSize(13, 13);
  41. clickedLabel->setStyleSheet("border:1px solid black");
  42. clickedLabel->setAlignment(Qt::AlignHCenter);
  43. setLabelGeometry(this->size());
  44. QFont font;
  45. font.setWeight(13);
  46. clickedLabel->setFont(font);
  47. }
  48. // 根据点击状态显示隐藏QGroupBox的控件
  49. void ExtendedGroupBox::slotOnChecked()
  50. {
  51. bool checked = state_ == STATE_NORMAL;
  52. if (checked) {
  53. //显示垂直边框
  54. this->setFlat(false);
  55. clickedLabel->setText("+");
  56. hidenWidget(true);
  57. state_ = STATE_EXPAND;
  58. } else {
  59. //隐藏垂直边框
  60. this->setFlat(true);
  61. clickedLabel->setText("-");
  62. hidenWidget(false);
  63. state_ = STATE_NORMAL;
  64. }
  65. }
  66. // 显示或隐藏QGroupBox里的控件
  67. void ExtendedGroupBox::hidenWidget(bool isVisible)
  68. {
  69. for (QObject* child : this->children()) {
  70. QWidget* widget = static_cast<QWidget*>(child);
  71. QString className = widget->metaObject()->className();
  72. if (widget != nullptr && hideWidgets_.contains(className)) {
  73. widget->setVisible(isVisible);
  74. }
  75. }
  76. }
  77. // 设置label的位置
  78. void ExtendedGroupBox::setLabelGeometry(QSize size)
  79. {
  80. int width = size.width() - 30;
  81. clickedLabel->setGeometry(width, 0, 13, 13);
  82. }
  83. // 窗口大小改变时更新label的位置
  84. void ExtendedGroupBox::resizeEvent(QResizeEvent*)
  85. {
  86. setLabelGeometry(this->size());
  87. }
  88. // 返回展开状态
  89. ExtendedGroupBox::State ExtendedGroupBox::getState() const
  90. {
  91. return state_;
  92. }

widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. class ExtendedGroupBox;
  5. class Widget : public QWidget {
  6. Q_OBJECT
  7. public:
  8. Widget(QWidget* parent = nullptr);
  9. ~Widget();
  10. private:
  11. ExtendedGroupBox* groupBox;
  12. };
  13. #endif // WIDGET_H

widget.cpp

  1. #include "widget.h"
  2. #include "extendedgroupbox.h"
  3. #include <QFormLayout>
  4. #include <QGroupBox>
  5. #include <QLayout>
  6. #include <QLineEdit>
  7. Widget::Widget(QWidget* parent)
  8. : QWidget(parent)
  9. {
  10. this->resize(350, 200);
  11. this->setWindowTitle("A collapsible GroupBox");
  12. QVBoxLayout* mainLayout = new QVBoxLayout(this);
  13. this->setLayout(mainLayout);
  14. groupBox = new ExtendedGroupBox("title", parent);
  15. mainLayout->addWidget(groupBox);
  16. QFormLayout* groupLayout = new QFormLayout(groupBox);
  17. groupBox->setLayout(groupLayout);
  18. QLabel* label1 = new QLabel("group1", groupBox);
  19. QLineEdit* lineEdit1 = new QLineEdit(groupBox);
  20. QLabel* label2 = new QLabel("group2", groupBox);
  21. QLineEdit* lineEdit2 = new QLineEdit(groupBox);
  22. groupLayout->addRow(label1, lineEdit1);
  23. groupLayout->addRow(label2, lineEdit2);
  24. }
  25. Widget::~Widget()
  26. {
  27. }

五、项目代码

ExtendedGroupBox.zip

六、参考链接

https://www.cnblogs.com/jiangbin/p/6752957.html