Qt按钮类02 QPushButton——大丙+Gemini

Qt按钮类02 QPushButton——大丙+Gemini

https://www.bilibili.com/video/BV1ff4y1C7CK

QPushButton 是 Qt 框架中应用最为广泛的文本/图标命令按钮控件。其核心功能主要继承自基类 QAbstractButton,开发者在实际业务逻辑中,大部分高层行为(如文本管理、图标渲染、状态机交互及信号发射机制)均通过调用其父类的多态接口实现。QPushButton 自身则在此基础上扩展了默认按钮(Default Button)语义以及级联上下文菜单(QMenu)的支持。

1. 核心 API 与属性控制

1.1 构造函数

// 1. 全参数构造:直接初始化图标、文本并挂载父对象
QPushButton(const QIcon &icon, const QString &text, QWidget *parent = nullptr);

// 2. 文本构造:初始化文本并挂载父对象(最常用)
QPushButton(const QString &text, QWidget *parent = nullptr);

// 3. 空白构造:仅指定父对象,后续通过成员函数配置属性
explicit QPushButton(QWidget *parent = nullptr);

1.2 默认按钮(Default Button)属性控制

在操作系统交互规范中,当一个窗口(通常是 QDialog 对话框)激活时,允许指定一个按钮为“默认按钮”。

// 判断当前按钮是否被设置为窗口的默认响应按钮
bool isDefault() const;

// 显式设置当前按钮为默认响应按钮。设置为 true 后,当用户在该窗口内按下键盘 Enter 键(或 Return 键)时,将自动触发此按钮的点击事件
void setDefault(bool);

1.3 按钮关联菜单接口

QPushButton 支持将其转换为“菜单按钮”,此时按钮将演变为多级级联交互的触发媒介。

// 将一个预先构建好的 QMenu 菜单与该按钮进行关联。
// 关联后按钮通常会在文本右侧渲染出一个小的下三角图标。点击按钮将不再发射 clicked() 信号,而是直接弹出该菜单。
void setMenu(QMenu *menu);

// [槽函数] 显式呼出(弹出)关联的菜单。若未关联菜单,则该函数不执行任何操作。
// 注意:该函数会以模态阻塞方式运行,直到关联的菜单被用户关闭后才会返回。
[slot] void showMenu();

2. 核心机制剖析:Checkable 状态机与菜单托管

2.1 触发信号的底层语义差异

QAbstractButton 基类中,定义了多个用于描述用户交互的信号。在开发中,必须根据业务场景进行精准区分:

  • released():物理鼠标在按钮区域内释放(弹起)的一瞬间发射。适合标准的命令型动作(一触即发)。
  • toggled(bool checked):当按钮的选中状态(State)发生翻转时发射。只有在按钮具备 checkable 属性时,该信号才有意义。

2.2 Checkable 状态机机制

默认情况下,QPushButton 是不具备状态记忆的,即点击后自动弹回(isCheckable() == false)。

通过调用 setCheckable(true),可以将按钮转换为自锁状态(或双稳态按钮)。此时按钮类似于开关:

  • 点击第一次,按钮下沉并保持选中状态,此时 isChecked() 返回 true
  • 点击第二次,按钮弹起恢复初始状态,此时 isChecked() 返回 false

3. 示例代码与实践

3.1 实践一:基础命令按钮与双稳态自锁按钮

  1. 作为普通按钮, 可以显示文本信息和图标
  2. 设置 checkable 按钮, 使其可以处于持续的被选中状态

mainwindow.cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->resize(1500, 1000);

    // 实例化中心复合容器以及垂直布局管理器
    QWidget *centralWindow = new QWidget(this);
    this->setCentralWidget(centralWindow);
    QVBoxLayout *vLayout = new QVBoxLayout(centralWindow);

    // ------------------ 1. 普通命令按钮 ------------------
    QPushButton *btnSakuya = new QPushButton("十六夜咲夜", this);
    btnSakuya->setCheckable(false); // 显式声明为非自锁状态(默认为 false)
    btnSakuya->resize(300, 100);
    btnSakuya->setIcon(QIcon(":/imgs/sakuya.jpg"));
    btnSakuya->setIconSize(QSize(100, 100));

    // 绑定物理释放信号
    connect(btnSakuya, &QPushButton::released, this, [=]() 
    {
        qDebug() << "砸 瓦鲁多!";
    });

    // ------------- 2. checkbale双稳态自锁按钮 -------------
    QPushButton *btnRemilia = new QPushButton(this);
    btnRemilia->setCheckable(true); // 激活自锁状态机,具备选中/非选中记忆
    btnRemilia->setText("蕾米莉亚 斯卡雷特");
    btnRemilia->setIcon(QIcon(":/imgs/remilia.png"));
    btnRemilia->setIconSize(QSize(100, 100));

    // 绑定状态翻转信号,Lambda 表达式入参 checked 反映当前实时状态
    connect(btnRemilia, &QPushButton::toggled, this, [=](bool checked) 
    {
        if (btnRemilia->isChecked()) 
        {
            qDebug() << "我是帝王!红魔馆的夜之帝王!状态:" << checked;
        } 
        else 
        {
            qDebug() << "(下蹲抱头)状态:" << checked;
        }
    });

    // 布局托管与弹簧填充
    vLayout->addWidget(btnSakuya);
    vLayout->addWidget(btnRemilia);
    vLayout->addStretch(); // 添加底部弹性弹簧,确保按钮垂直紧凑排列
}

MainWindow::~MainWindow() 
{
}

3.2 实践二:下挂组件式菜单按钮

通过 setMenu() 接口将 QMenuQPushButton 进行级联绑定,实现点击按钮自动下弹出菜单。

mainwindow.cpp构造函数:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->resize(1600, 1000);

    // 1. 初始化菜单基架按钮
    QPushButton *menuBtn = new QPushButton(this);
    menuBtn->setText("Choose Your Character");
    menuBtn->move(600, 500);
    menuBtn->resize(300, 100);
    menuBtn->setCheckable(true);

    // 2+3. 创建+关联菜单
    QMenu* menu = new QMenu;
    QAction* actReimu = menu->addAction(QIcon(":/imgs/reimu.jpg"), "reimu");
    QAction* actMarisa = menu->addAction(QIcon(":/imgs/marisa.png"), "marisa");
    QAction* actSakuya = menu->addAction(QIcon(":/imgs/sakuya.jpg"), "sakuya");
    QAction* actRemilia = menu->addAction(QIcon(":/imgs/remilia.png"), "remilia");
    menuBtn->setMenu(menu);

    // 4. 将菜单与按钮完成级联互锁绑定
    // 绑定后,用户点击 menuBtn 会在后台自动调用 QMenu::exec(globalPos),实现自动化模态渲染
    menuBtn->setMenu(menu);

    // 5. 注册信号槽
    connect(actReimu, &QAction::triggered, this, [=]()
    {
        qDebug() << "您选择了:博丽灵梦";
    });

    connect(actMarisa, &QAction::triggered, this, [=]()
    {
        qDebug() << "您选择了:雾雨魔理沙";
    });

    connect(actSakuya, &QAction::triggered, this, [=]()
    {
        qDebug() << "您选择了:十六夜咲夜";
    });

    connect(actRemilia, &QAction::triggered, this, [=]()
    {
        qDebug() << "您选择了:蕾米莉亚";
    });
}
posted @ 2026-06-10 21:56  学习笔记草稿存放账号  阅读(8)  评论(0)    收藏  举报