• Qt实战12.可自由展开的ToolBox


    1 需求描述

    需求就很简明了,Qt自带的QToolBox同时只能展开一个页面,客户要求可同时展开多个,这种只好自定义实现了。网上也能找到很多实现,但还是感觉亲力亲为的好,毕竟自己动手丰衣足食嘛。

    2 设计思路


    主要有两部分,分别是ToolPage和ToolBox,ToolBox可包含多个ToolPage,ToolPage分为标题栏(QPushButton)和内容区(QWidget),设计简单明了。点击QPushButton后,循环展开/折叠内容区。

    3 代码实现

    3.1 ToolPage

    这个就没啥说的了,主要完成标题栏和内容区的布局,点击标题栏按钮将内容区隐藏,再次点击展示内容区,代码如下:

    #ifndef TOOLPAGE_H
    #define TOOLPAGE_H
    
    #include <QWidget>
    
    namespace Ui {
    class ToolPage;
    }
    
    class QFormLayout;
    class QLabel;
    class ToolPage : public QWidget
    {
        Q_OBJECT
    public:
        explicit ToolPage(QWidget *parent = nullptr);
        ~ToolPage();
    public slots:
        void addWidget(const QString &title, QWidget *widget);
        void expand();
        void collapse();
    private slots:
        void onPushButtonFoldClicked();
    private:
        Ui::ToolPage *ui;
        bool m_bIsExpanded;
        QLabel *m_pLabel;
    };
    #endif // TOOLPAGE_H
    
    #include "ToolPage.h"
    #include "ui_ToolPage.h"
    
    #include <QDebug>
    #include <QFormLayout>
    #include <QDebug>
    #include <QHBoxLayout>
    #include <QLabel>
    #include <QFile>
    
    ToolPage::ToolPage(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::ToolPage),
        m_bIsExpanded(true),
        m_pLabel(nullptr)
    {
        ui->setupUi(this);
    
        ui->widgetContent->setAttribute(Qt::WA_StyledBackground);
    
        m_pLabel = new QLabel(this);
        m_pLabel->setFixedSize(20, 20);
        m_pLabel->setPixmap(QPixmap(":/img/down-arrow.png").scaled(m_pLabel->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
        QHBoxLayout *layout = new QHBoxLayout(ui->pushButtonFold);
        layout->setContentsMargins(0, 0, 5, 0);
        layout->addStretch(1);
        layout->addWidget(m_pLabel);
    
        QFile file(":/qss/toolpage.qss");
        if (file.open(QIODevice::ReadOnly)) {
            setStyleSheet(file.readAll());
        }
        file.close();
    
        connect(ui->pushButtonFold, &QPushButton::clicked, this, &ToolPage::onPushButtonFoldClicked);
    }
    
    ToolPage::~ToolPage()
    {
        delete ui;
    }
    
    void ToolPage::addWidget(const QString &title, QWidget *widget)
    {
        ui->pushButtonFold->setText(title);
        ui->verticalLayoutContent->addWidget(widget);
    }
    
    void ToolPage::expand()
    {
        ui->widgetContent->show();
        m_bIsExpanded = true;
        m_pLabel->setPixmap(QPixmap(":/img/down-arrow.png").scaled(m_pLabel->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }
    
    void ToolPage::collapse()
    {
        ui->widgetContent->hide();
        m_bIsExpanded = false;
        m_pLabel->setPixmap(QPixmap(":/img/left-arrow.png").scaled(m_pLabel->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }
    
    void ToolPage::onPushButtonFoldClicked()
    {
        if (m_bIsExpanded) {
            collapse();
        } else {
            expand();
        }
    }
    

    需要提示一点,QPushButton文字可以通过QSS进行对齐方式设置,但是图标的对齐方式貌似不能设置,这里直接用一个水平布局将QLabel设置到按钮上,简单可靠,轻松达成目标。

    3.2 ToolBox

    ToolBox主要给外部用,将传入的QWidget传入到ToolPage中,ToolPage自动填充到内容区,再将ToolPage添加到垂直布局中,完成布局,代码如下:

    #ifndef TOOLBOX_H
    #define TOOLBOX_H
    
    #include <QWidget>
    
    namespace Ui {
    class ToolBox;
    }
    
    class QVBoxLayout;
    class ToolBox : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit ToolBox(QWidget *parent = nullptr);
        ~ToolBox();
        void addWidget(const QString &title, QWidget *widget);
    private:
        Ui::ToolBox *ui;
        QVBoxLayout *m_pContentVBoxLayout;
    };
    #endif // TOOLBOX_H
    
    #include "ToolBox.h"
    #include "ui_ToolBox.h"
    #include "ToolPage.h"
    
    #include <QVBoxLayout>
    
    ToolBox::ToolBox(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::ToolBox),
        m_pContentVBoxLayout(nullptr)
    {
        ui->setupUi(this);
    
        QWidget *widget = new QWidget(this);
        m_pContentVBoxLayout = new QVBoxLayout;
        m_pContentVBoxLayout->setContentsMargins(0, 0, 0, 0);
        m_pContentVBoxLayout->setSpacing(2);
    
        QVBoxLayout *vBoxLayout = new QVBoxLayout(widget);
        vBoxLayout->setContentsMargins(0, 0, 0, 0);
        vBoxLayout->addLayout(m_pContentVBoxLayout);
        vBoxLayout->addStretch(1);
    
        ui->scrollArea->setWidget(widget);
    }
    
    ToolBox::~ToolBox()
    {
        delete ui;
    }
    
    void ToolBox::addWidget(const QString &title, QWidget *widget)
    {
        ToolPage *page = new ToolPage(this);
        page->addWidget(title, widget);
        m_pContentVBoxLayout->addWidget(page);
    }
    

    3.3 简单使用

    使用很简单了,只需要调用ToolBox唯一的一个接口即可:

    void addWidget(const QString &title, QWidget *widget);

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        setWindowTitle(QStringLiteral("自定义ToolBox演示  Qt小罗"));
    
        ToolBox *toolBox = new ToolBox(this);
        toolBox->addWidget(QStringLiteral("Qt小罗"), new Form());
        toolBox->addWidget(QStringLiteral("Qt小罗"), new Form());
        toolBox->addWidget(QStringLiteral("Qt小罗"), new Form());
        toolBox->addWidget(QStringLiteral("Qt小罗"), new Form());
    
        setCentralWidget(toolBox);
    }
    

    到此,自定义ToolBox就实现了,更多功能可自行拓展。

    4 总结

    Qt基本控件的使用搞清楚了,结合一些小技巧,实现复杂的自定义控件是一件很轻松的事情,熟能生巧,万事皆如此。

    5 下载

    完整代码

    © 版权声明
    文章版权归作者所有,未经允许请勿转载。【QQ交流:115124903】
    THE END
  • 相关阅读:
    Netty ChannelOption.SO_BACKLOG配置
    ChannelOption.TCP_NODELAY
    如何使用XStream框架编码UTF8?
    NETTY keeplive 参数,心跳检测
    cnpm 无法加载文件 ENode.jsnodeglobalcnpm.ps1,因为在此系统上禁止运行脚本。
    vue框架值props
    vue重要方法解释
    vue系列之组件间数据共享
    限制微信环境中微信修改h5页面字体大小
    from_data参数放在body里 调用接口
  • 原文地址:https://www.cnblogs.com/luoxiang/p/14449127.html
Copyright © 2020-2023  润新知