当前位置: 首页 > news >正文

Qt自定义控件-抽屉盒子

一、项目运行结果

二、项目目录结构

三、源码

仓库:

https://gitee.com/dieyong/Qt_Learning.git

项目:

CustomComponent/lockerwidget_/lockerwidget1_/LockerWidget

四、关键代码

1、lockerwidget.h

#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

2、lockerwidget.cpp

#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("QPushButton{background-color:rgb(250,250,250)}"); this->setMinimumHeight(36);//没有设置最小高度,按钮会缩成一条线 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; scrollArea->setWidgetResizable(true);//没有它,滚动区域不会让内部 widget 填满视口宽度,导致内容挤在左上角 mainLayout->addWidget(scrollArea); scrollWidget = new QWidget(this); 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); } }

3、form_mainui.h

#ifndef FORM_MAINUI_H #define FORM_MAINUI_H #include <QWidget> namespace Ui { class Form_mainui; } class Form_mainui : public QWidget { Q_OBJECT public: explicit Form_mainui(QWidget *parent = nullptr); ~Form_mainui(); private: Ui::Form_mainui *ui; }; #endif // FORM_MAINUI_H

4、form_mainui.cpp

#include "form_mainui.h" #include "ui_form_mainui.h" #include "lockerwidget.h" #include <QSizePolicy> #include <QPushButton> #include <QLabel> #include <QHBoxLayout> Form_mainui::Form_mainui(QWidget *parent) : QWidget(parent), ui(new Ui::Form_mainui) { ui->setupUi(this); //创建抽屉盒子对象 LockerWidget* lockerWidget = new LockerWidget; QVBoxLayout* modelLayout = new QVBoxLayout(ui->modelWidget); modelLayout->setMargin(0); modelLayout->addWidget(lockerWidget); ui->modelWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);//没有拉伸策略,不随窗口扩展 QStringList names; names << "电源设备" << "支路设备" << "变压器设备" << "负荷元件" << "测量设备" << "分布式电源" << "连接元件" << "通信元件" << "逻辑设备" << "其它元件" << "自定义元件"; QList<QWidget*> drawerWidgets; for (int i = 0; i < names.count(); ++i) { QWidget* w = new QWidget(ui->modelWidget); QHBoxLayout* hLayout = new QHBoxLayout(w); QPushButton *btn = new QPushButton("test", w); btn->setFixedHeight(36); btn->setStyleSheet(R"( QPushButton {background-color: #4de85a;border: 1px solid #CCCCCC;border-radius: 4px;color: #FFFFFF;font-size: 18px;padding: 0 12px;} QPushButton:hover { color: #FFFF88; } QPushButton:pressed { color: #FFD700; } )"); QLabel *label = new QLabel("test", w); label->setFixedHeight(36); label->setStyleSheet(R"( QLabel { background-color: #E3F2FD; border: 1px solid #CCCCCC; border-radius: 4px; font-size: 18px; color: #333333; padding: 0 12px; } )"); hLayout->addWidget(btn); hLayout->addStretch();//加一根弹簧 hLayout->addWidget(label); drawerWidgets.append(w); } QList<QWidget*> widgets = drawerWidgets; //向抽屉盒子中添加抽屉 lockerWidget->add_locker(names,widgets); } Form_mainui::~Form_mainui() { delete ui; }

五、参考

Qt--自定义抽屉盒子控件_qt 抽屉控件-CSDN博客

http://www.zskr.cn/news/1387860.html

相关文章:

  • ops-transformer的MoE算子,让混合专家模型训练快5倍
  • 昇腾CANN社区治理:一个PR从提交到合并的全过程
  • 告别多模型集成噩梦:DMXAPI如何用“改两行配置”统一调用DeepSeek、豆包等大模型
  • PostgreSQL CASE语句深度解析:从类型推导到执行计划优化
  • Arm A64 SIMD浮点指令FMAXNMV与FMINNMP详解
  • 嘉楠第一季营收6270万美元:同比降24% 净亏8870万美元
  • PTA L1-005 考试座位号:用C语言结构体搞定考场查询系统(附完整代码)
  • 别再傻傻分不清了!Zynq 7010的MIO、EMIO和GPIO到底怎么用?一个按键控制LED的实战例子
  • 2024终极微信抢红包助手:无需ROOT的智能自动抢红包解决方案
  • 多平台同稿如何一键改写?5款AI文案工具对比帮你避坑
  • Django 从 0 到 1 打造完整电商平台:支付结果处理与订单状态更新
  • 别再乱装 Skill 了!这 4 组神级 Skill 让你的 Claude Code 直接封神[特殊字符]【2026 最新实测】
  • 别再乱装 Skill 了!这 4 组神级 Skill 让你的 Claude Code 直接封神[特殊字符]【2026 最新实测】
  • libwebsockets回调函数详解:从‘诡异设计’到‘掌控全局’的客户端状态机实战
  • 避开PWM重叠的坑:Simulink仿真单电阻电流重构的移相实战(附模型)
  • 保姆级教程:用STM32F103驱动TM1620数码管,从看懂手册到点亮第一个数字
  • 国产多模态大模型:重塑安防监控的“智慧之眼”
  • 分布式--4--雪花算法
  • CANoe测试进阶:如何为你的CAPL脚本引入外部DLL(以UDS 27服务安全算法为例)
  • 国内专业商贸一体化软件排行:5款主流产品实测对比
  • mv command
  • 从传统CMS到JAMstack架构:内容即服务与无头CMS实战解析
  • Excel PI()函数:15位精度的数学常量锚点与工程计算基石
  • 工业质检数据不平衡难题:用Stable Diffusion生成缺陷图像提升分割模型性能4.6%
  • UE5 Paper2D地形材质底层解析:PaperTerrainMaterial.h源码契约深度解读
  • 机器人渗透测试与安全防御的博弈论方法
  • STM32的‘心跳’与‘重启’:深入聊聊晶振与复位电路的设计门道(附PCB布局避坑指南)
  • 扣子空间专属提示词模板:专业任务拆解专家
  • NextChat开源对话系统:自托管、多模型与全链路可控AI工作流
  • ngx_http_process_request_header