一、前言
因项目需求,需要用到类似于抽屉的控件,归类摆放不同的器件,熟悉Qt的朋友一定马上联想到了QToolBox
,我一开始也是这么做的,但是QToolBox
有个弊端:它同一时刻只能打开一个抽屉,即抽屉间是互斥的关系。虽然能满足归类的需求,但是实际使用过程中很不便利,我希望能同时打开多个抽屉,抽屉的开关由我自己控制,实现真正的自由。
二、思路
采用QWidget::setVisible(bool)
来选择是否显示控件
每添加一个抽屉,就创建一个按钮和一个widget,然后对按钮和widget进去垂直布局,例如:
按钮设置setVisible(true)
,widget设置setVisible(false)
;
然后对所有把所有按钮链接到同一个槽函数中,用QObject::sender()
获取发送对象,然后根据按钮的状态来判断是否显示该按钮对应的widget
三、运行效果
四、详细代码
#ifndef LOCKERWIDGET_H
#define LOCKERWIDGET_H
#include <QWidget>
#include <QToolButton>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QDebug>
#include <QPixmap>
#include <QHBoxLayout>
#define OPEN_ICON ":/images/Boxopen.png"
#define CLOSE_ICON ":/images/Boxclose.png"
class LockerButton : public QPushButton
{
Q_OBJECT
public:
explicit LockerButton(QWidget* parent = nullptr);
void SetImageLabel(const QPixmap &pixmap);
void SetTextLabel(QString text);
QLabel* GetImageHandle();
QLabel* GetTextHandle();
bool isOpen;
private:
// 按钮图标
QLabel* m_imageLabel;
// 按钮文字
QLabel* m_textLabel;
};
//==================================================================
class LockerWidget : public QWidget
{
Q_OBJECT
public:
explicit LockerWidget(QWidget* parent = nullptr);
~LockerWidget();
void add_locker(QStringList names,QList<QWidget*> widgets);
void deleteAllitemsOfLayout(QLayout* layout);
QScrollArea* get_scrollArea() const
{
return this->scrollArea;
}
QWidget* get_scrollWidget() const
{
return this->scrollWidget;
}
private:
void SetUpUI();
QVBoxLayout* mainLayout;
QVBoxLayout* layout_widgetScroll;
LockerButton* m_Button;
QWidget* m_Widget;
QList<LockerButton*> Buttons;
QList<QWidget*> Widgets;
QScrollArea* scrollArea;
QWidget* scrollWidget;
QPixmap pixmap_open;
QPixmap pixmap_close;
public slots:
void slot_btn(bool);
};
#endif // LOCKERWIDGET_H
#include "lockerwidget.h"
LockerButton::LockerButton(QWidget* parent)
: QPushButton(parent)
{
m_imageLabel = new QLabel;
m_imageLabel->setFixedWidth(32);
m_imageLabel->setScaledContents(true);
m_imageLabel->setStyleSheet("QLabel{background-color:transparent;}");
m_textLabel = new QLabel;
m_textLabel->setStyleSheet("QLabel{background-color:transparent;}");
QHBoxLayout* mainLayout = new QHBoxLayout;
mainLayout->addWidget(m_imageLabel);
mainLayout->addWidget(m_textLabel);
mainLayout->setMargin(0);
mainLayout->setSpacing(4);
this->setLayout(mainLayout);
this->setStyleSheet("background-color:rgb(250,250,250)}");
isOpen = false;
}
void LockerButton::SetImageLabel(const QPixmap &pixmap)
{
m_imageLabel->setPixmap(pixmap);
}
void LockerButton::SetTextLabel(QString text)
{
m_textLabel->setText(text);
}
QLabel* LockerButton::GetImageHandle()
{
return m_imageLabel;
}
QLabel* LockerButton::GetTextHandle()
{
return m_textLabel;
}
//==================================================================
LockerWidget::LockerWidget(QWidget* parent) : QWidget(parent)
{
mainLayout = new QVBoxLayout;
mainLayout->setMargin(0);
mainLayout->setSpacing(0);
this->setLayout(mainLayout);
scrollArea = new QScrollArea;
mainLayout->addWidget(scrollArea);
scrollWidget = new QWidget(this);
scrollWidget->setFixedHeight(3000);
layout_widgetScroll = new QVBoxLayout(scrollWidget);
layout_widgetScroll->setMargin(0);
layout_widgetScroll->setSpacing(0);
pixmap_open = QPixmap(OPEN_ICON);
pixmap_close = QPixmap(CLOSE_ICON);
}
LockerWidget::~LockerWidget()
{
LockerButton* l = nullptr;
QWidget* w = nullptr;
if(Buttons.count()>0) {
for(int i=0; i<Buttons.count(); ++i) {
l = Buttons[i];
if(l != nullptr) {
delete l;
l = nullptr;
}
}
}
if(Widgets.count()>0) {
for(int i=0; i<Widgets.count(); ++i) {
w = Widgets[i];
if(w != nullptr) {
delete w;
w = nullptr;
}
}
}
}
void LockerWidget::add_locker(QStringList names,QList<QWidget*> widgets)
{
if(names.count() != widgets.count()) {
return;
}
for(int i=0; i<names.count(); ++i) {
m_Button = new LockerButton(this);
m_Button->SetTextLabel(names[i]);
m_Button->SetImageLabel(pixmap_close);
connect(m_Button,&LockerButton::clicked,this,&LockerWidget::slot_btn);
m_Widget = new QWidget(this);
m_Widget->setVisible(false);
QHBoxLayout* layout_widget = new QHBoxLayout(m_Widget);
layout_widget->setMargin(0);
layout_widget->setSpacing(0);
layout_widget->addWidget(widgets[i]);
Buttons.push_back(m_Button);
Widgets.push_back(m_Widget);
}
deleteAllitemsOfLayout(layout_widgetScroll);
for(int i=0; i<Buttons.count(); ++i) {
layout_widgetScroll->addWidget(Buttons[i]);
layout_widgetScroll->addWidget(Widgets[i]);
}
layout_widgetScroll->addStretch();
scrollArea->setWidget(scrollWidget);
}
void LockerWidget::deleteAllitemsOfLayout(QLayout* layout)
{
QLayoutItem *child;
while ((child = layout->takeAt(0)) != nullptr)
{
///setParent为NULL,防止删除之后界面不消失
if(child->widget())
{
child->widget()->setParent(nullptr);
}
else if(child->layout())
{
deleteAllitemsOfLayout(child->layout());
}
delete child;
}
}
void LockerWidget::slot_btn(bool)
{
LockerButton *btn = qobject_cast<LockerButton *>(sender());
int record = -1;
for(int i=0; i<Buttons.count(); ++i) {
if(btn == Buttons[i]) {
record = i;
}
}
if(record == -1) {
return;
}
btn->isOpen = !btn->isOpen;
if(btn->isOpen) { //true
//切换图标
btn->SetImageLabel(pixmap_open);
//显示widget
Widgets[record]->setVisible(true);
}else { //false
//切换图标
btn->SetImageLabel(pixmap_close);
//隐藏widget
Widgets[record]->setVisible(false);
}
}
//==================================================================
五、代码使用指南
//创建抽屉盒子对象
LockerWidget* lockerWidget = new LockerWidget;
//准备好抽屉widget(内部放啥自己布局决定)
widget_BranchDevice = new QWidget(modelWidget); //支路设备
widget_PowerDevice = new QWidget(modelWidget); //电源设备
widget_MeasureUnit = new QWidget(modelWidget); //测量设备
widget_TransformerDevice = new QWidget(modelWidget); //变压器设备
widget_Load = new QWidget(modelWidget); //负荷元件
widget_CleanPower = new QWidget(modelWidget); //分布式电源
widget_ConmuniceteUnit = new QWidget(modelWidget); //通信元件
widget_ConnectUnit = new QWidget(modelWidget); //连接元件
widget_LogicDevice = new QWidget(modelWidget); //逻辑设备
widget_othersUnit = new QWidget(modelWidget); //其它元件
widget_userDIY = new QWidget(modelWidget); //用户自定义元件
//准备好抽屉的名字集合、widget集合
QStringList names;
names << "电源设备" << "支路设备" << "变压器设备" << "负荷元件" << "测量设备"
<< "分布式电源" << "连接元件" << "通信元件" << "逻辑设备" << "其它元件"
<< "自定义元件";
QList<QWidget*> widgets;
widgets << widget_PowerDevice << widget_BranchDevice << widget_TransformerDevice
<< widget_Load << widget_MeasureUnit << widget_CleanPower << widget_ConnectUnit
<< widget_ConmuniceteUnit << widget_LogicDevice << widget_othersUnit << widget_userDIY;
//向抽屉盒子中添加抽屉
lockerWidget->add_locker(names,widgets);