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 下載

完整代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM