目录
3.2 -> click,press,release,toggled 的区别
1 -> 概念
在构建图形用户界面(GUI)时,提供清晰、直观的选项选择机制是提升用户体验的关键。Qt 框架中的 QRadioButton(单选按钮)控件,正是为满足 “多选一” 的精确场景而设计的核心元素。它源于其物理世界原型——老式汽车收音机上的机械按钮,按下其中一个则会弹出之前被按下的那个,确保了任何时候都只有一个选项处于激活状态。
1.1 -> 核心概念:互斥性选择
QRadioButton 最根本、最重要的特性是 互斥性。这意味着在一组单选按钮中,用户只能且必须选择其中的一个选项。当一个选项被选中时,之前选中的选项会自动变为未选中状态。这种设计天然地适用于那些所有选项相互排斥、不可兼得的场景。
例如:
- 性别选择:男 / 女 / 其他
- 评分等级:优 / 良 / 差
- 支付方式:信用卡 / 支付宝 / 微信支付
- 分辨率设置:1920*1080 / 1280*720 / 800*600
这种 “非此即彼” 的交互模式,能够清晰地引导用户做出唯一选择,避免了歧义。
1.2 -> 视觉呈现与状态
一个典型的 QRadioButton 由两部分组成:
圆形指示器:一个空心的圆形,当被选中时,内部会填充一个实心圆点。
文本标签:紧邻指示器显示的描述性文字,用于明确告知用户该选项代表的意义。
它拥有两种主要状态:
选中状态:圆形指示器内有一个实心点。这是该选项被激活的视觉反馈。
未选中状态:圆形指示器为空心的。
此外,为了满足更复杂的需求,QRadioButton 还支持第三种状态:
- 部分选中状态:在某些特殊情况下(例如通过 setAutoExclusive(false) 暂时关闭自动互斥),它可以被设置为一种 “未决” 或 “三态” 模式。但这是一种非典型用法,绝大多数情况下使用的是标准的选中 / 未选中两种状态。
1.3 -> 分组机制
单个 QRadioButton 本身并不具备互斥性。互斥的行为并非由按钮自身实现,而是由它们所处的 分组 所强制规定的。
Qt 提供了两种主要的分组方式:
父容器自动分组:这是最常见和简便的方法。将多个 QRadioButton 放置在同一个父控件内(例如同一个
QGroupBox
、QWidget
或QFrame
),Qt 会自动识别它们属于同一逻辑组,并为其建立互斥关系。这种方式布局直观,管理方便。使用 QButtonGroup 抽象分组:对于更复杂的界面,当单选按钮分散在不同的布局或容器中,但又属于同一个逻辑选择集时,
QButtonGroup
类就变得至关重要。它是一个不可见的逻辑容器,可以将任何地方的 QRadioButton 添加进去,从而在逻辑上将它们编为一组,实现互斥选择,而不受其物理布局的限制。这提供了极大的灵活性。
2 -> 相关属性
QRadioButton 是单选按钮。可以让我们在多个选项中选择一个。
作为 QAbstractButton 和 QWidget 的子类,对于 QRadioButton 同样适用。
QAbstractButton 中和 QRadioButton 关系比较大的属性:
属性 | 说明 |
checkable | 是否能选中 |
checked | 是否已经被选中。checkable 是 checked 的前提条件 |
autoExclusive | 是否排他 选中一个按钮之后是否会取消其他按钮的选中 对于 QRadioButton 来说默认就是排他的 |
3 -> 代码示例
3.1 -> 选择性别
1. 在界面上创建一个 label,和 3个 单选按钮
设置的文本如下。3个 单选按钮的 objectName 分别为 radioButton_male、radioButton_female 和
radioButton_other
2. 修改 widget.cpp,编辑 3个 QRadioButton 的 slot 函数
void Widget::on_radioButton_male_clicked()
{
// 把界面上的 label 的内容进行更新
ui->label->setText("您选择的性别为: 男");
}
void Widget::on_radioButton_female_clicked()
{
// 把界面上的 label 的内容进行更新
ui->label->setText("您选择的性别为: 女");
}
void Widget::on_radioButton_other_clicked()
{
// 把界面上的 label 的内容进行更新
ui->label->setText("您选择的性别为: 其他");
}
3. 运行程序,可以看到随着选择不同的单选按钮,label 中的提示文字就会随之变化
4. 当前代码中,如果程序启动,则不会选择任何选项
可以修改代码,让程序启动默认选中性别男
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 设置默认选项
ui->radioButton_male->setChecked(true);
ui->label->setText("您选择的性别为: 男");
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_radioButton_male_clicked()
{
// 把界面上的 label 的内容进行更新
ui->label->setText("您选择的性别为: 男");
}
void Widget::on_radioButton_female_clicked()
{
// 把界面上的 label 的内容进行更新
ui->label->setText("您选择的性别为: 女");
}
void Widget::on_radioButton_other_clicked()
{
// 把界面上的 label 的内容进行更新
ui->label->setText("您选择的性别为: 其他");
}
此时运行程序,即可以看到性别男已经被选中了。
5. 当前代码中,也可以禁用 “其他” 被选中
修改 widget.cpp 的构造函数
ui->radioButton_other->setCheckable(false);
运行程序,可以看到,点击 “其他” 按钮时,虽然不会被选中,但是可以触发点击事件,使上面的 label 显示性别为其他。
使用 setEnabled 是更加彻底的禁用按钮的方式。此时该按钮无法被选中,也无法响应任何输入。
ui->radioButton_other->setEnabled(false);
3.2 -> click,press,release,toggled 的区别
- clicked 表示一次 “点击”
- pressed 表示鼠标 “按下”
- released 表示鼠标 “释放”
- toggled 表示按钮状态切换
1. 在界面上创建四个单选按钮
objectName 分别为 radioButton、radioButton_2、radioButton_3 和 radioButton_4。
2. 依次给四个单选按钮创建 clicked槽函数、pressed槽函数、released槽函数 和 toggled槽函数
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_radioButton_clicked(bool checked)
{
// 此处从 checked 就表示了当前 radioButton 的选中状态.
qDebug() << "cliched: " << checked;
}
void Widget::on_radioButton_2_pressed()
{
qDebug() << "pressed";
}
void Widget::on_radioButton_3_released()
{
qDebug() << "released";
}
void Widget::on_radioButton_4_toggled(bool checked)
{
// checked 状态发生改变, 就会触发这个信号.
qDebug() << "toggled: " << checked;
}
3. 运行程序,可以看到
- clicked 是一次鼠标按下 + 鼠标释放触发的
- pressed 是鼠标按下触发的
- released 是鼠标释放触发的
- toggled 是 checked 属性改变时触发的
总的来说,toggled 是最适合 QRadioButton 的。
3.3 -> 单选框分组
1. 在界面上创建 9个 单选框,用来模拟麦麦点餐界面
objectName 分别为 radioButton ~ radioButton_9
此时直接运行程序,可以看到,这 9个 QRadioButton 之间是排他的。
我们希望的是每一组的内部来控制排他,但是组和组之间不能排他。
2. 引入 QButtonGroup 进行分组
修改 widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QButtonGroup>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QButtonGroup* group1 = new QButtonGroup(this);
QButtonGroup* group2 = new QButtonGroup(this);
QButtonGroup* group3 = new QButtonGroup(this);
group1->addButton(ui->radioButton);
group1->addButton(ui->radioButton_2);
group1->addButton(ui->radioButton_3);
group2->addButton(ui->radioButton_4);
group2->addButton(ui->radioButton_5);
group2->addButton(ui->radioButton_6);
group3->addButton(ui->radioButton_7);
group3->addButton(ui->radioButton_8);
group3->addButton(ui->radioButton_9);
}
Widget::~Widget()
{
delete ui;
}
再次执行程序,可以看到可以按照正确的分组方式来完成排他了。
4 -> 总结
QRadioButton 是 Qt 控件库中一个功能专一而强大的组件。它通过其固有的互斥性,完美解决了需要用户进行单一选择的交互需求。其有效性不仅依赖于控件本身,更在于通过父容器或 QButtonGroup 进行合理分组的机制。在与 QCheckBox 的对比中,其应用场景的区别变得尤为清晰。最终,遵循良好的UI/UX设计原则来使用它,是构建出清晰、高效、用户友好的桌面应用程序界面的重要一环。
感谢各位大佬支持!!!
互三啦!!!