Qt 中提供的按钮,都是抽象基类 QAbstractButton 的实现。
想要简单了解这些按钮的通用的功能,可以翻阅这篇: Qt Widgets 之 QAbstractButton

一、概述

Qt 自带的按钮控件应对不同的场景需求,主要有:

按钮类型 类名 特点 适用场景
命令按钮 QPushButton 最常用的按钮类型,执行即时操作 大多数需要触发操作的场景
工具按钮 QToolButton 工具栏上的专用按钮,支持多种显示样式,可带弹出菜单 工具栏、小型操作按钮
单选按钮 QRadioButton 从多个选项中选择一个 设置选项,互斥选择
复选框 QCheckBox 开关选项或多项选择,
支持三态(选中/未选中/部分选中)
启用/禁用功能,多项选择

关于按钮在Qt模块的继承关系如图所示:

QObject
QWidget
QPaintDevice
QAbstractButton
QPushButton
QToolButton
QRadioButton
QCheckBox

二、QPushButton(命令按钮)

QPushButton 是 Qt 中最常用的按钮控件,通常用于点击触发操作,也可以采用按下、释放触发。
主要有以下特性:

  • 支持文本和图标显示
  • 可以设置为默认按钮(对话框中按Enter键触发的按钮)
  • 支持可选中(toggle)行为
  • 支持自动重复功能

构造及基本用法

#include <QPushButton>

// 创建按钮
// 方式1: 直接创建并设置父对象
QPushButton* button1 = new QPushButton(parentWidget);

// 方式2: 创建时指定文本
QPushButton* button2 = new QPushButton("Click Me", parentWidget);

// 方式3: 创建时指定图标和文本
QPushButton* button3 = new QPushButton(QIcon(":/images/icon.png"), "Click Me", parentWidget);


// 设置图标
button->setIcon(QIcon(":/images/icon.png"));
button->setIconSize(QSize(32, 32));

// 设置按钮属性
button->setEnabled(true); // 启用按钮,禁用为false,按钮变灰
button->setChecked(true);   // 设置选中状态,按钮高亮
button->setDefault(true); // 设置为默认按钮(回车键触发)
button->setFlat(false); // 设置为非扁平样式(默认有3D效果)

其他用法

  • void setDefault(bool enabled)
    设置按钮是否为默认按钮。默认按钮在对话框中通常有特殊外观,并响应Enter键。

  • bool isDefault() const
    返回按钮是否为默认按钮。

  • void setAutoDefault(bool enabled)
    设置按钮是否自动成为默认按钮。当设置为true时,按钮在获得焦点时会自动成为默认按钮。

  • bool autoDefault() const
    返回按钮是否自动成为默认按钮。

信号连接

QPushButton 自带多个信号来触发响应用户交互。
常用信号有:

  • 按钮被点击时发出(最常用)
    void clicked(bool checked = false);

  • 按钮被按下时发出
    void pressed();

  • 按钮被释放时发出
    void released();

  • 可选中按钮状态改变时发出
    void toggled(bool checked);

信号连接示例:

// 连接clicked信号(最常用)
connect(button, &QPushButton::clicked, this, &MyClass::onButtonClicked);
// 使用lambda表达式
connect(button, &QPushButton::clicked, [=]() {
    qDebug() << "Button clicked!";
});

// 可检查按钮的状态变化
button->setCheckable(true); // 设置为可检查
connect(button, &QPushButton::toggled, [=](bool checked) {
    qDebug() << "Button state:" << (checked ? "Checked" : "Unchecked");
});

样式表示例

// 基本样式
button->setStyleSheet(
    "QPushButton {"
    "   background-color: #4CAF50;"
    "   border: none;"
    "   color: white;"
    "   padding: 10px 20px;"
    "   border-radius: 8px;"
    "}"
    "QPushButton:hover {"
    "   background-color: #45a049;"
    "}"
    "QPushButton:pressed {"
    "   background-color: #3d8b40;"
    "}"
    "QPushButton:disabled {"
    "   background-color: #cccccc;"
    "   color: #666666;"
    "}"
    "QPushButton:checked {" // 针对可检查按钮的选中状态
    "   background-color: #2196F3;"
    "}"
);

三、QToolButton(工具按钮)

QToolButton是工具按钮控件,通常用于工具栏中,比如软件的“File”,“about” 等按钮,提供了工具按钮的特有功能,如弹出菜单和各种显示模式。
主要特性:

  • 通常用于工具栏中
  • 支持各种显示模式(只显示图标、只显示文本等)
  • 支持弹出菜单
  • 可以设置为自动提升(只在鼠标悬停时显示3D效果)

构造及基本用法

#include <QToolButton>
#include <QMenu>

// 创建工具按钮
QToolButton *toolButton = new QToolButton(parentWidget);

// 设置图标
toolButton->setIcon(QIcon(":/images/tool.png"));


// 设置显示样式
toolButton->setToolButtonStyle(Qt::ToolButtonIconOnly); // 只显示图标
// 可选样式:
// Qt::ToolButtonIconOnly - 只显示图标
// Qt::ToolButtonTextOnly - 只显示文本
// Qt::ToolButtonTextBesideIcon - 文本在图标旁边
// Qt::ToolButtonTextUnderIcon - 文本在图标下方
// Qt::ToolButtonFollowStyle - 跟随应用程序风格

// 下拉菜单
// 创建弹出菜单
QMenu *menu = new QMenu(&window);
menu->addAction("Action 1");
menu->addAction("Action 2");
menu->addAction("Action 3");
// 设置弹出菜单
toolButton->setMenu(menu);
toolButton->setPopupMode(QToolButton::MenuButtonPopup);  // 带菜单箭头的按钮

其他用法

  • void setToolButtonStyle(Qt::ToolButtonStyle style)
    设置工具按钮的显示风格。

  • Qt::ToolButtonStyle toolButtonStyle() const
    返回工具按钮的显示风格。

  • void setAutoRaise(bool enable)
    设置是否自动提升(只在鼠标悬停时显示3D效果)。

  • bool autoRaise() const
    返回是否自动提升。

  • void setPopupMode(QToolButton::ToolButtonPopupMode mode)
    设置弹出菜单的模式。

  • QToolButton::ToolButtonPopupMode popupMode() const
    返回弹出菜单的模式。

  • void setMenu(QMenu *menu)
    设置弹出菜单。

  • QMenu *menu() const
    返回弹出菜单。

样式表示例

toolButton->setStyleSheet(
    "QToolButton {"
    "   background-color: #f0f0f0;"
    "   border: 1px solid #cccccc;"
    "   border-radius: 4px;"
    "   padding: 5px;"
    "}"
    "QToolButton:hover {"
    "   background-color: #e0e0e0;"
    "}"
    "QToolButton:pressed {"
    "   background-color: #d0d0d0;"
    "}"
    "QToolButton::menu-button {"
    "   width: 20px;"
    "   border-left: 1px solid #cccccc;"
    "}"
);

四、QRadioButton(单选按钮)

QRadioButton是单选按钮控件,允许用户从多个选项中选择一个,通常需要与QButtonGroup一起使用以实现互斥选择。
主要特性:

  • 支持单选功能(同一组内互斥)
  • 适合单项选择场景
  • 默认具有自动排他性(同父组件的单选按钮自动互斥)

基本用法

#include <QRadioButton>
#include <QButtonGroup>

// 创建单选按钮
QRadioButton *radio1 = new QRadioButton("Option 1", parentWidget);
QRadioButton *radio2 = new QRadioButton("Option 2", parentWidget);
QRadioButton *radio3 = new QRadioButton("Option 3", parentWidget);

// 设置默认选中
radio1->setChecked(true);

// 方法一:使用按钮组管理互斥行为(推荐)
QButtonGroup *buttonGroup = new QButtonGroup(parentWidget);
buttonGroup->addButton(radio1);
buttonGroup->addButton(radio2);
buttonGroup->addButton(radio3);
buttonGroup->setExclusive(true); // 确保只能选中一个
// 方法二:默认同一父组件下,就是互斥的,无需额外设置

// 获取选中的按钮
QRadioButton *selectedRadio = qobject_cast<QRadioButton*>(buttonGroup->checkedButton());
if (selectedRadio) {
    qDebug() << "Selected:" << selectedRadio->text();
}

信号连接

// 单个按钮的状态变化
connect(radio1, &QRadioButton::toggled, [=](bool checked) {
    if (checked) {
        qDebug() << "Radio 1 selected";
    }
});

// 按钮组的信号
connect(buttonGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
        [=](QAbstractButton *button) {
    qDebug() << "Button clicked:" << button->text();
});

样式表示例

radio1->setStyleSheet(
    "QRadioButton {"
    "   spacing: 5px;" // 文本和指示器之间的间距
    "   color: #333333;"
    "   font-size: 14px;"
    "}"
    "QRadioButton::indicator {"
    "   width: 16px;"
    "   height: 16px;"
    "}"
    "QRadioButton::indicator:unchecked {"
    "   border: 2px solid #999999;"
    "   border-radius: 8px;"
    "   background-color: white;"
    "}"
    "QRadioButton::indicator:checked {"
    "   border: 2px solid #2196F3;"
    "   border-radius: 8px;"
    "   background-color: #2196F3;"
    "}"
);

五、QCheckBox(复选框)

QCheckBox是复选框控件,允许用户选择多个选项,提供了复选框的特有功能。
主要特性:

  • 支持两种状态(选中/未选中)或三种状态(选中/部分选中/未选中)
  • 适合多项选择场景
  • 可以分组使用,但不互斥(与QRadioButton不同)

基本用法

#include <QCheckBox>

// 创建复选框
QCheckBox *checkBox = new QCheckBox("Enable feature", parentWidget);

// 设置三态支持(可选)
checkBox->setTristate(true); // 启用三态

// 设置检查状态
checkBox->setCheckState(Qt::Checked); // 2 完全选中
// 其他状态:
// Qt::Unchecked - 0 未选中
// Qt::PartiallyChecked - 1 部分选中

// 获取状态
// Qt::CheckState state = checkBox->checkState();
if (checkBox->checkState() == Qt::Checked) {
    qDebug() << "Checkbox is checked";
}

其他方法:

  • void setTristate(bool y = true)
    设置复选框是否支持三态模式。

  • bool isTristate() const
    返回复选框是否支持三态模式。

  • void setCheckState(Qt::CheckState state)
    设置复选框的状态(包括三态)。

  • Qt::CheckState checkState() const
    返回复选框的当前状态(包括三态)。

信号连接

// 状态变化信号
connect(checkBox, &QCheckBox::stateChanged, [=](int state) {
    if (state == Qt::Checked) {
        qDebug() << "Checked";
    } else if (state == Qt::Unchecked) {
        qDebug() << "Unchecked";
    } else if (state == Qt::PartiallyChecked) {
        qDebug() << "Partially checked";
    }
});

样式表示例

checkBox->setStyleSheet(
    "QCheckBox {"
    "   spacing: 5px;"
    "   color: #333333;"
    "   font-size: 14px;"
    "}"
    "QCheckBox::indicator {"
    "   width: 16px;"
    "   height: 16px;"
    "}"
    "QCheckBox::indicator:unchecked {"
    "   border: 2px solid #999999;"
    "   background-color: white;"
    "}"
    "QCheckBox::indicator:checked {"
    "   border: 2px solid #2196F3;"
    "   background-color: #2196F3;"
    "}"
    "QCheckBox::indicator:indeterminate {" // 部分选中状态
    "   border: 2px solid #2196F3;"
    "   background-color: #90CAF9;"
    "}"
);

七、经验与实践

1. 按钮分组管理

// 创建按钮组
QButtonGroup *buttonGroup = new QButtonGroup(parentWidget);

// 添加按钮到组中
buttonGroup->addButton(radio1);
buttonGroup->addButton(radio2);
buttonGroup->addButton(checkBox); // 也可以混合不同类型

// 设置互斥性(默认情况下,QRadioButton会自动互斥)
buttonGroup->setExclusive(true); // 设置组内按钮互斥

// 连接组信号
connect(buttonGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
        [=](QAbstractButton *button) {
    qDebug() << "Button in group clicked:" << button->text();
});

2. 动态按钮创建

// 动态创建多个按钮
QList<QPushButton*> buttons;
for (int i = 0; i < 5; ++i) {
    QPushButton *btn = new QPushButton(QString("Button %1").arg(i+1), parentWidget);
    connect(btn, &QPushButton::clicked, [=]() {
        handleButtonClick(i);
    });
    buttons.append(btn);
}

3. 设置快捷键

// 方式一:设置快捷键
button->setShortcut(QKeySequence("Ctrl+S")); // Ctrl+S触发按钮
button->setShortcut(Qt::Key_Return);        // 回车键触发按钮

// 方式二:使用"&"符号在文本中指定快捷键(Alt+字母)
button->setText("&Save"); // Alt+S触发按钮
QPushButton *button = new QPushButton("&Save", this);  // Alt+S

// 方法3:使用QAction关联快捷键
QAction *saveAction = new QAction("Save", this);
saveAction->setShortcut(QKeySequence::Save);
connect(saveAction, &QAction::triggered, this, &MainWindow::save);
button->addAction(saveAction);

4. 设置辅助功能

设置辅助功能属性,主要针对于视障人士会用到屏幕阅读器,这个功能就会被用到。

button->setAccessibleName("Save Button");
button->setAccessibleDescription("Saves the current document");

5. 自定义按钮绘制

class CustomButton : public QPushButton {
    Q_OBJECT
public:
    explicit CustomButton(QWidget* parent = nullptr) 
        : QPushButton(parent) {
        // 自定义初始化
    }
    
protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);
        // 自定义绘制代码
        painter.setRenderHint(QPainter::Antialiasing);
        
        // 绘制背景
        painter.setBrush(QColor("#2196F3"));
        painter.drawRoundedRect(rect(), 10, 10);
        
        // 绘制文本
        painter.setPen(Qt::white);
        painter.drawText(rect(), Qt::AlignCenter, text());
    }
};

八、常见问题与解决方案

  1. 按钮点击无响应

    • 检查按钮是否被禁用(setEnabled(false)或者isEnabled()返回false)
    • 确认信号槽连接是否正确
    • 检查是否有其他控件覆盖了按钮
    • 检查事件过滤器是否阻止了事件传递
    • 检查父组件是否拦截了事件
  2. 样式表不生效

    • 确保样式表语法正确
    • 检查选择器是否正确匹配按钮类型
    • 确认样式表特异性足够(使用更具体的选择器)
  3. 国际化支持

    // 对所有用户可见文本使用tr()函数包装
    QPushButton *button = new QPushButton(tr("Click Me"), parentWidget);
    QCheckBox *checkBox = new QCheckBox(tr("Enable feature"), parentWidget);
    button->setText(tr("Save"));
    
  4. 内存管理

    • 始终为按钮设置父对象,以便自动内存管理。若没有设置父对象,则需要delete
    • 使用QPointer跟踪按钮指针,避免悬空指针。
  5. 布局管理

    • 最好将将按钮添加到布局中,不使用绝对坐标。

持续更新中。。。。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐