Qt/C++学习系列之QButtonGroup的简单使用

前言

在练手项目中,使用了QButtonGroup。项目需求有互斥的要求,在使用QRadioButton的基础上,叠加使用QButtonGroup。通过使用了解到,除QRadioButton以外,QCheckBox也可以使用,提供统一的管理。


QButtonGroup

QButtonGroup是用于对一组按钮进行统一管理的类,可以定义多个QRadioButton或QCheckBox进行分组管理。从而确保其按钮按下的互斥逻辑或统一处理的逻辑。

刨析源码

cpp 复制代码
class Q_WIDGETS_EXPORT QButtonGroup : public QObject
{
    Q_OBJECT

    Q_PROPERTY(bool exclusive READ exclusive WRITE setExclusive)
public:
    explicit QButtonGroup(QObject *parent = Q_NULLPTR);
    ~QButtonGroup();

    void setExclusive(bool);
    bool exclusive() const;

    void addButton(QAbstractButton *, int id = -1);
    void removeButton(QAbstractButton *);

    QList<QAbstractButton*> buttons() const;

    QAbstractButton * checkedButton() const;
    // no setter on purpose!

    QAbstractButton *button(int id) const;
    void setId(QAbstractButton *button, int id);
    int id(QAbstractButton *button) const;
    int checkedId() const;

Q_SIGNALS:
    void buttonClicked(QAbstractButton *);
    void buttonClicked(int);
    void buttonPressed(QAbstractButton *);
    void buttonPressed(int);
    void buttonReleased(QAbstractButton *);
    void buttonReleased(int);
    void buttonToggled(QAbstractButton *, bool);
    void buttonToggled(int, bool);

private:
    Q_DISABLE_COPY(QButtonGroup)
    Q_DECLARE_PRIVATE(QButtonGroup)
    friend class QAbstractButton;
    friend class QAbstractButtonPrivate;
};

借助AI可以快速刨析一下源码,同时学习一下有关QButtonGroup的属性、成员函数:

  • 添加和移除按钮: addButton() 为将按钮添加到按钮组中,这里要注意(QAbstractButton *, int id = -1),id默认为-1,意味着如果在未添加按钮的情况下,直接做移除操作会出现-1的情况。 在很多时候要注意按钮组内是否有按钮,在程序编译的时候要初始化,进行按钮的添加。 removeButton() 为移除按钮。
  • 设置互斥性: setExclusive() 将分类为一组的按钮进行互斥设置。对于单选按钮组,通常设置为互斥(true),这样组内只能选择一个按钮;对于复选按钮组,通常设置为非互斥(false)。 exclusive() const:检查按钮组是否为互斥的,并反馈。
  • 获取当前选中的按钮: checkedButton() 获取当前选中的按钮。
  • 通过 ID 操作按钮 button(int id) const:通过 ID 获取按钮。 setId(QAbstractButton *button, int id):为按钮设置一个唯一的 ID。 id(QAbstractButton *button) const:获取按钮的 ID。 checkedId() const:返回当前选中按钮的 ID。如果没有按钮被选中,则返回 -1。
  • 信号和槽:(因为继承QObject,这意味着它可以使用 Qt 的信号和槽机制。) QButtonGroup 提供了一些信号,例如 buttonClicked() 和 buttonPressed(),可以用于响应按钮的点击事件。 buttonClicked(QAbstractButton *):当按钮被点击时发出信号,传递按钮的指针。 buttonClicked(int):当按钮被点击时发出信号,传递按钮的 ID。 buttonPressed(QAbstractButton *)、buttonPressed(int):当按钮被按下时发出信号。 buttonReleased(QAbstractButton *)、buttonReleased(int):当按钮被释放时发出信号。 buttonToggled(QAbstractButton *, bool)、buttonToggled(int, bool):当按钮的状态切换时发出信号(仅适用于复选按钮)。

具体使用

在项目中,需要通过不同的QRadioButton来引导后续关于QComboBox的使用。那么在项目中,我是这么处理的。

界面设计

这里我拖了QgroupBox,在里面包含了三个QRadioButton,并且在选择QRadioButton的基础上需要刷新点亮对应的QComboBox。

具体函数使用

初始化

cpp 复制代码
	boardButtonGroup = new QButtonGroup(this);
    boardButtonGroup->addButton(ui->RBtn_xz_1, 0); // ID为0
    boardButtonGroup->addButton(ui->RBtn_xz_2, 1); // ID为1
    boardButtonGroup->addButton(ui->RBtn_xz_3, 2); // ID为2
	boardButtonGroup->setExclusive(true);
    for (int i = 1; i <= 12; ++i)
    {
        ui->CB_xz_1->addItem(QString("选择2_%1").arg(i));
        ui->CB_xz_2->addItem(QString("选择3_%1").arg(i));
    }
  • 创建QButtonGroup,并给QRadioButton进行标号。
  • addItem初始化QComboBox控件的内容。
  • setExclusive设置互斥逻辑。

信号与槽函数(两种方式)

  • 脱离QButtonGroup进行控制:
cpp 复制代码
connect(ui->RBtn_xz_2, &QRadioButton::toggled, ui->CB_xz_1, &QComboBox::setEnabled);
    connect(ui->RBtn_xz_3, &QRadioButton::toggled, ui->CB_xz_2, &QComboBox::setEnabled);

这里是将QRadioButton的 toggled 信号连接到 QComboBox 的 setEnabled 槽。

  • 使用QButtonGroup
cpp 复制代码
handleButtonClicked(boardButtonGroup->checkedId());

handleButtonClicked 函数:传入当前按钮组中选中的按钮的 ID。这里的checkedId()就是使用到QButtonGroup的ID。

cpp 复制代码
QObject::connect(boardButtonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked),
                     [this](int id) {
        handleButtonClicked(id);
    });

这里是QButtonGroup 的 buttonClicked 信号连接到一个 lambda 表达式中。通过捕捉到的ID来进行handleButtonClicked函数的处理。

cpp 复制代码
void MainWindow::handleButtonClicked(int id) {
    switch (id) {
        case 0: // RBtn_xz_1 被选中
            ui->CB_xz_1->setEnabled(false);
            ui->CB_xz_2->setEnabled(false);
            break;
        case 1: // RBtn_xz_2 被选中
            ui->CB_xz_1->setEnabled(true);
            ui->CB_xz_2->setEnabled(false);
            break;
        case 2: // RBtn_xz_3 被选中
            ui->CB_xz_1->setEnabled(false);
            ui->CB_xz_2->setEnabled(true);
            break;
        default:
            ui->CB_xz_1->setEnabled(false);
            ui->CB_xz_2->setEnabled(false);
            break;
    }
}

这个代码就是根据按钮的 ID 设置 QComboBox 的启用状态。

--

总结

本文从QButtonGroup的源码角度进行分析,仅仅简单介绍了QButtonGroup的使用。对于项目中的使用,两种方式那更倾向于哪一种呢?

相关推荐
荟K5 小时前
Trae连接终端ubuntu电脑
ubuntu·trae
程序员爱钓鱼6 小时前
Node.js 的应用场景:为什么越来越多企业选择它?
前端·node.js·trae
程序员爱钓鱼6 小时前
为什么选择 Node.js?一文深入理解
前端·node.js·trae
Mintopia8 小时前
AIGC 技术标准制定:Web 行业协同的必要性与难点
人工智能·aigc·trae
飞哥数智坊20 小时前
告别繁琐部署:TRAE SOLO 帮我一键跑通 Z-Image 模型
人工智能·trae·solo
程序员爱钓鱼1 天前
使用 Node.js 批量导入多语言标签到 Strapi
前端·node.js·trae
ohyeah2 天前
用 Coze 打造你的教育智能客服:从想法到前端集成的完整实践
前端·coze·trae
豆包MarsCode3 天前
用 SOLO Coder 搭建 3D 机器人项目
trae
风止何安啊3 天前
收到字节的短信:Trae SOLO上线了?尝尝鲜,浅浅做个音乐播放器
前端·html·trae
天天摸鱼的java工程师3 天前
从 0 到 1:我用 Java + Vue 实现了文件上传压缩功能(附完整项目结构)
trae