QToolButton是一个 “带图标的按钮”
通过设置可以调整图标和文本的显示方式,如只显示图标、只显示文本、文本显示在图标旁边或下方等。

1. 效果演示

本案例展示如何设置工具按钮的样式表,并且实现页面切换的效果
toolbutton

2. 属性和方法

QToolButton有很多属性和方法,完整的可查看帮助文档。这里列出常用的属性和方法:

2.1 设置图标和文本

void setIcon(const QIcon &icon);        // 设置图标
void setIconSize(const QSize &size);    // 设置图标大小
void setText(const QString &text);      // 设置文本

void setToolButtonStyle(Qt::ToolButtonStyle style);    // 设置按钮风格

其中,Qt::ToolButtonStyle是一个枚举,可取的值如下:

枚举 含义
Qt::ToolButtonIconOnly 0 只显示图标
Qt::ToolButtonTextOnly 1 只显示文字
Qt::ToolButtonTextBesideIcon 2 文本在图标一侧
Qt::ToolButtonTextUnderIcon 3 文本在图标下方

2.2 设置菜单

// 设置弹出菜单, 以及弹出菜单模式
void setMenu(QMenu* menu);
void setPopupMode(ToolButtonPopupMode mode);

ToolButton提供了三种弹出菜单模式:

  • DelayedPopup
    默认模式,长按按钮后延迟弹出菜单。这通常用于需要用户长按以确认操作的场景。
  • MenuButtonPopup
    点击按钮箭头图标后立即弹出菜单。这种模式下,工具按钮显示一个特殊的箭头以指示菜单的存在。
  • InstantPopup
    点击按钮时立即弹出菜单,无延迟。这种模式下,按钮自身的动作不触发,而是直接显示菜单。

2.3 信号槽

// 当按钮被点击时发出该信号。如果是可选中的按钮,checked 参数将指示按钮是否被选中。
void clicked(bool checked = false)

// 当其选中状态改变时发出该信号
void toggled(bool checked)

// 当与按钮关联的下拉菜单中的某个动作被触发时发出该信号
void triggered(QAction *action)

3. 从零实现

从零写代码实现整体效果,以演示工具按钮的属性以及信号槽的用法

3.1 布局

在UI设计师界面,拖拽对应的控件,修改显示的文字、控件的名称,然后完成布局

  • 最顶层的MyWidget采用水平布局,左侧是leftWidget,右侧是stackedWidget,并将MyWidget布局的边距和间隙都设置为0
  • 设置leftWidget的背景色为rgb(220, 240, 255)stackedWidget的背景色为rgb(235, 245, 255)
  • 修改ToolButton的属性:
    • toolButtonStyle设置为ToolButtonTextUnderIcon
    • icon属性中,选择一个系统图标,并将iconSize设置为64*64
    • text设置为 “演示文本”,fontPoint Size设置为16

布局完成效果如下:
qt-base

3.2 添加资源文件

把用到的图标,作为资源文件添加到项目中,如下:
qt-base

3.3 代码实现

3.3.1 工具按钮样式表

首先,为了保证10个工具按钮可以互斥地选中,在mywidget.h中声明一个按钮组,如下:

#include <QButtonGroup>

class MyWidget : public QWidget {

private:
    QButtonGroup *btnGroup;
};

然后,循环地设置工具按钮的属性和样式表,如下:

MyWidget::MyWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MyWidget) {

    this->setWindowTitle("明王讲QT | 第二章 常用控件 | 2.11 工具按钮QToolButton (WX: coding4096)");

    // 左侧设置一个最大宽度
    ui->leftWidget->setMaximumWidth(250);

    // clang-format off

    // 工具按钮的文字
    QStringList names;  // 按钮文字集合
    names << "基础组件"  << "图标字体" << "高级组件" << "图表(官方)" << "图表(三方)"
          << "仪表盘" << "语法高亮" << "天气预报" << "精美换肤" << "未完待续...";

    // 工具按钮的图标
    QStringList icons;
    icons << ":/res/base.png"
          << ":/res/iconfont.png"
          << ":/res/advance.png"
          << ":/res/chart.png"
          << ":/res/customplot.png"
          << ":/res/gauge.png"
          << ":/res/hilight.png"
          << ":/res/weather.png"
          << ":/res/skin.png"
          << ":/res/more.png";

    // 工具按钮
    QList<QToolButton*> toolBtns;
    toolBtns << ui->toolBtnBasic
             << ui->toolBtnIcon
             << ui->toolBtnAdvance
             << ui->toolBtnQChart
             << ui->toolBtnQCustomPlot
             << ui->toolBtnGauge
             << ui->toolBtnHighlight
             << ui->toolBtnWeather
             << ui->toolBtnSkin
             << ui->toolBtnMore;

    btnGroup = new QButtonGroup(this);

    // clang-format on

    for (int i = 0; i < names.count(); i++) {
        // 设置样式、大小策略
        toolBtns[i]->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
        toolBtns[i]->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

        // 设置文字
        toolBtns[i]->setText(QString("%1").arg(names.at(i)));

        // 设置图标
        QPixmap pix = QPixmap(icons[i]);
        toolBtns[i]->setIcon(QIcon(pix));
        toolBtns[i]->setIconSize(QSize(64, 64));

        //设置按钮可选中-按下类似复选框的功能
        toolBtns[i]->setCheckable(true);

        // 设置按钮的样式
        toolBtns[i]->setStyleSheet(R"(
            QToolButton {
                border:1px solid #A0A0A0;
                font:18px "Microsoft YaHei";
                color:#386487;
                padding:5px;
                border-radius:5px;
                background: #DEF0FE;
            }
            QToolButton:hover {
                background:#C0DEF5;
            }
            QToolButton:checked {
                background:#C0DEF5;
            }
        )");

        // 将按钮添加到 btnGroup
        btnGroup->addButton(toolBtns[i], i);
    }
}

此时,运行效果:
qt-base

3.3.2 添加10个页面

首先,添加一个C++类,让它继承自QWidget,并在页面的构造中添加一个标签,如下:
qt-base

然后,继续添加剩余的9个页面,可以按照上边的方法,继续添加

也可以直接复制文件,并修改对应的文件名和类名,以及CMakeList.txt文件

10个页面添加完成后,效果如下:
qt-base

3.3.3 页面切换

首先,在mywidget.cpp中为stackedWidget中添加10个页面,如下:

#include "advance_widget.h"
#include "basic_widget.h"
#include "chart_widget.h"
#include "customplot_widget.h"
#include "gauge_widget.h"
#include "highlight_widget.h"
#include "icon_widget.h"
#include "more_widget.h"
#include "skin_widget.h"
#include "weather_widget.h"

MyWidget::MyWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MyWidget) {
    // ...
    ui->stackedWidget->addWidget(new BasicWidget());
    ui->stackedWidget->addWidget(new IconWidget());
    ui->stackedWidget->addWidget(new AdvanceWidget());
    ui->stackedWidget->addWidget(new ChartWidget());
    ui->stackedWidget->addWidget(new CustomplotWidget());
    ui->stackedWidget->addWidget(new GaugeWidget());
    ui->stackedWidget->addWidget(new HighlightWidget());
    ui->stackedWidget->addWidget(new WeatherWidget());
    ui->stackedWidget->addWidget(new SkinWidget());
    ui->stackedWidget->addWidget(new MoreWidget());
}

然后,在mywidget.h/mywidget.cpp中,声明、关联、实现信号槽,如下:

// mywidget.h
class MyWidget : public QWidget {

private slots:
    void onBtnGroupClicked(int id);
};

// mywidget.cpp
class MyWidget : public QWidget {

    // ...
    
    for (int i = 0; i < names.count(); i++) {
        // ...
        // 关联信号槽
        connect(btnGroup, &QButtonGroup::idClicked, this, &MyWidget::onBtnGroupClicked);
    }
}

void MyWidget::buttonClicked() {
    stackedWidget->setCurrentIndex(btnGroup->checkedId());
}

最后,在mywidget.cpp中,默认选中第一个工具按钮,如下:

MyWidget::MyWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MyWidget) {
    // ...
    ui->toolBtnBasic->click();
}

4. 点赞、获取源码

看到这里的小伙伴,去B站给明王一个【免费的点赞】吧,你的支持,是我持续更新优质内容的动力,感谢~

源码下载地址
链接: https://pan.baidu.com/s/1OwqKHh_o5kRYofprjHY3xA
提取码: ming