Qt--自定义抽屉盒子控件

本文介绍了一种基于Qt的自定义组件实现方案,通过QWidget的setVisible方法控制多个抽屉式的控件显示与隐藏,实现了多抽屉同时展开的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

因项目需求,需要用到类似于抽屉的控件,归类摆放不同的器件,熟悉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);
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贝勒里恩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值