Qt QPushButton 图标与文字组合显示
在 Qt 中,将图标与文字组合显示在 QPushButton 上有多种实现方式。本文将详细介绍各种方案,包括代码示例、优缺点分析和最佳实践。
重要提示:本指南基于 Qt 6.x,Qt 5.x 可能有轻微差异。
目录
方案1:图标在左、文字在右(默认布局)
这是最常用的布局方式,图标在左侧,文字在右侧。
// ===== Widget 构造函数中 =====
// 第一步:设置图标和大小
ui->pushButton_send->setIcon(QIcon(":/icon/paper_plane.svg"));
ui->pushButton_send->setIconSize(QSize(20, 20));
// 第二步:调用 setText 显式设置按钮文本(如果在 .ui 中未设置)
ui->pushButton_send->setText("发送");
// 第三步:设置样式表(为图标和文字留出充足空间)
ui->pushButton_send->setStyleSheet(
"QPushButton {"
" background-color: #16a34a;" // 背景色:绿色
" color: white;" // 文字颜色:白色
" font-size: 16px;" // 字体大小
" font-weight: 500;" // 字体粗细(0-900,500=Medium)
" border: none;" // 无边框
" border-radius: 6px;" // 圆角半径(px)
" padding: 8px 16px;" // 内边距:上下8px,左右16px(关键!)
" text-align: left;" // 文字对齐方式
"}"
"QPushButton:hover {" // 鼠标悬停状态
" background-color: #15803d;" // 悬停时背景变深
"}"
"QPushButton:pressed {" // 鼠标按下状态
" background-color: #166534;" // 按下时背景更深
"}"
"QPushButton:focus {" // 获得焦点状态
" outline: 2px solid #0080FF;" // 焦点框
"}"
);
效果示意: 图标左对齐,文字右侧

方案2:图标在右、文字在左(反转布局)
使用 setLayoutDirection() 可以反转图标和文字的显示方向。
// 反转布局方向(从右到左)
ui->pushButton_send->setLayoutDirection(Qt::RightToLeft);
// 设置图标
ui->pushButton_send->setIcon(QIcon(":/icon/paper_plane.svg"));
ui->pushButton_send->setIconSize(QSize(20, 20));
// 设置文字(必须显式设置)
ui->pushButton_send->setText("发送");
// 应用样式表
ui->pushButton_send->setStyleSheet(
"QPushButton {"
" background-color: #16a34a;"
" color: white;"
" font-size: 16px;"
" padding: 8px 16px;"
" border: none;"
" border-radius: 6px;"
"}"
"QPushButton:hover { background-color: #15803d; }"
);
工作原理:
Qt 会自动检测 LayoutDirection,当设置为 Qt::RightToLeft 时,按钮内部的元素排列顺序反转。
效果示意: 文字左对齐,图标右侧

限制条件:
- 仅支持左右反转(不支持其他排列方式)
- 必须调用
setText()设置文字(资源中的文字才能显示)
方案3:图标在上、文字在下(自定义类)
当需要垂直布局时,需要创建自定义按钮类。
customButton.h
#ifndef CUSTOMBUTTON_H
#define CUSTOMBUTTON_H
#include <QPushButton>
class CustomButton : public QPushButton {
Q_OBJECT
public:
CustomButton(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent *event) override;
};
#endif // CUSTOMBUTTON_H
customButton.cpp
#include "customButton.h"
#include <QPainter>
#include <QStyleOptionButton>
#include <QStylePainter>
// 构造函数,直接调用基类QPushButton的构造函数
CustomButton::CustomButton(QWidget *parent) : QPushButton(parent) {
}
// 重写paintEvent事件,实现自定义绘制
void CustomButton::paintEvent(QPaintEvent *event) {
// 如果没有设置图标,则使用默认的QPushButton绘制行为
if (icon().isNull()) {
QPushButton::paintEvent(event);
return;
}
// 准备按钮的样式选项,包含按钮的当前状态、大小、文本等信息
QStyleOptionButton option;
initStyleOption(&option);
// 保存原始的文本和图标,因为稍后我们需要清除它们以便先绘制背景
const QString text = option.text;
const QIcon icon = option.icon;
option.text.clear(); // 清空文本,避免背景绘制时同时绘制文本
option.icon = QIcon(); // 清空图标,避免背景绘制时同时绘制图标
// 使用QStylePainter来绘制按钮背景(只绘制背景,不含文本和图标)
QStylePainter painter(this);
painter.drawControl(QStyle::CE_PushButton, option);
// 计算布局参数
// 判断是否有文本需要显示
const bool hasText = !text.isEmpty();
// 获取图标大小,如果未显式设置则默认使用16x16
QSize iconSize;
if (this->iconSize().isValid()) {
iconSize = this->iconSize();
} else {
iconSize = QSize(16, 16);
}
// 计算图标与文本之间的间距,使用布局垂直间距样式参数(如果没有文本则间距为0)
int spacing = 0;
if (hasText) {
spacing = style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing, &option, this);
}
// 计算整个内容(图标 + 间距 + 文本)的总高度
int contentHeight = iconSize.height();
if (hasText) {
contentHeight += spacing + painter.fontMetrics().height();
}
// 计算垂直起始位置,使内容在按钮内垂直居中
const int y = (height() - contentHeight) / 2;
// 确定图标的绘制模式:根据按钮状态(是否启用、鼠标悬停等)选择对应的图标模式
QIcon::Mode mode;
if (option.state & QStyle::State_Enabled) {
if (option.state & QStyle::State_MouseOver) {
mode = QIcon::Active;
} else {
mode = QIcon::Normal;
}
} else {
mode = QIcon::Disabled;
}
// 图标状态:如果按钮处于“按下”或“选中”状态则使用On,否则使用Off
QIcon::State state;
if (option.state & QStyle::State_On) {
state = QIcon::On;
} else {
state = QIcon::Off;
}
// 从原始图标中获取对应大小和状态的QPixmap
const QPixmap pixmap = icon.pixmap(iconSize, mode, state);
// 计算图标的水平位置(居中)
const int iconX = (width() - iconSize.width()) / 2;
// 在计算好的位置绘制图标
painter.drawPixmap(iconX, y, pixmap);
// 如果有文本,则绘制文本
if (hasText) {
// 设置画笔颜色为按钮文本颜色
painter.setPen(palette().buttonText().color());
// 绘制文本的区域:从图标下方开始,高度为剩余空间,水平居中
painter.drawText(QRect(0, y + iconSize.height() + spacing, width(), height() - y - iconSize.height() - spacing),
Qt::AlignHCenter, text);
}
}
使用示例
CustomButton *customBtn = new CustomButton(this);
customBtn->resize(80, 80);
customBtn->setIcon(QIcon(":/icon/paper_plane.svg"));
customBtn->setText("发送");
customBtn->setStyleSheet(
"QPushButton {"
" background-color: #16a34a;" // 背景色:绿色
" color: white;" // 文字颜色:白色
" font-size: 16px;" // 字体大小
" font-weight: 500;" // 字体粗细(0-900,500=Medium)
" border: none;" // 无边框
" border-radius: 6px;" // 圆角半径(px)
"}"
"QPushButton:hover {" // 鼠标悬停状态
" background-color: #15803d;" // 悬停时背景变深
"}"
"QPushButton:pressed {" // 鼠标按下状态
" background-color: #166534;" // 按下时背景更深
"}"
);
效果示意:

方案4:使用布局组装(最灵活)
通过 QLayout 可以创建更灵活的组合,支持自定义间距、对齐、动画等。
// 第一步:创建容器按钮(作为布局的父容器)
QPushButton *customSendBtn = new QPushButton(this);
customSendBtn->setFixedSize(100, 100); // 固定大小:100×100 像素
customSendBtn->move(50, 50); // 设置按钮位置(相对于父窗口)
// 第二步:设置按钮样式(背景、圆角等)
customSendBtn->setStyleSheet(
"QPushButton {"
" background-color: #16a34a;" // 背景色:绿色
" color: white;" // 文字颜色:白色
" font-size: 16px;" // 字体大小
" font-weight: 500;" // 字体粗细(0-900,500=Medium)
" border: none;" // 无边框
" border-radius: 6px;" // 圆角半径(px)
"}"
"QPushButton:hover {" // 鼠标悬停状态
" background-color: #15803d;" // 悬停时背景变深
"}"
"QPushButton:pressed {" // 鼠标按下状态
" background-color: #166534;" // 按下时背景更深
"}"
);
// 第三步:创建垂直布局(上→下排列)
QVBoxLayout *layout = new QVBoxLayout(customSendBtn);
// 配置布局参数
layout->setContentsMargins(0, 0, 0, 0); // 布局与按钮边界的距离(无)
layout->setSpacing(5); // 控件之间的间距:5 像素
layout->setAlignment(Qt::AlignCenter); // 内容居中
// 第四步:创建并配置图标标签
QLabel *iconLabel = new QLabel();
// 从 SVG 转换为 20×20 的像素图
QPixmap iconPixmap = QIcon(":/icon/paper_plane.svg").pixmap(20, 20);
iconLabel->setPixmap(iconPixmap);
iconLabel->setAlignment(Qt::AlignCenter); // 图标居中
iconLabel->setScaledContents(false); // 不自动缩放(保持原大小)
// 设置固定大小,防止标签自动调整大小
iconLabel->setFixedSize(20, 20);
// 第五步:创建并配置文字标签
QLabel *textLabel = new QLabel("发送");
textLabel->setAlignment(Qt::AlignCenter); // 文字水平和垂直居中
textLabel->setStyleSheet(
"color: white;" // 文字颜色:白色
"font-size: 12px;" // 字体大小 12px
"font-weight: bold;" // 字体加粗
"background: transparent;" // 背景透明(继承父容器背景)
);
textLabel->setMaximumHeight(20); // 限制文字标签高度
// 第六步:将控件按顺序添加到布局(上→下)
layout->addStretch(); // 在图标前添加弹性空间
layout->addWidget(iconLabel); // 图标在上
layout->addSpacing(2); // 固定间距 2px
layout->addWidget(textLabel); // 文字在下
layout->addStretch(); // 在文字后添加弹性空间
布局结构图:


浙公网安备 33010602011771号