在Qt中,单选按钮(QRadioButton)和复选按钮(QCheckBox)是两种常用的用户界面控件,它们的主要区别在于选择行为和用途:

QRadioButton(单选按钮)

  1. 选择行为:单选按钮用于在一组选项中选择一个选项。组内的单选按钮是互斥的,这意味着在同一组内只有一个按钮可以被选中。
  2. 用途:通常用于需要用户在多个选项中选择一个的时候,例如选择性别、选择支付方式等。
  3. 默认行为:单选按钮一般是成组使用,通过将它们放置在同一个父容器(如QGroupBoxQButtonGroup)中实现互斥选择。
  4. 外观和操作:单选按钮通常是一个圆形的控件,点击后内部会填充一个小圆点来表示选中状态。

示例代码(单选按钮):

QGroupBox *groupBox = new QGroupBox("Select an option"); 
QRadioButton *radio1 = new QRadioButton("Option 1"); 
QRadioButton *radio2 = new QRadioButton("Option 2"); 
QRadioButton *radio3 = new QRadioButton("Option 3"); 
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(radio1); 
vbox->addWidget(radio2); 
vbox->addWidget(radio3); 
groupBox->setLayout(vbox); // 将radio1设置为默认选中 radio1->setChecked(true);

QCheckBox(复选按钮)

  1. 选择行为:复选按钮用于在多个选项中进行独立的选择。每个复选按钮都是独立的,可以单独选中或取消选中。
  2. 用途:通常用于需要用户选择多个选项或者启用/禁用某些设置的时候,例如选择兴趣爱好、启用功能选项等。
  3. 默认行为:复选按钮是独立的,选中一个复选按钮不会影响其他复选按钮的状态。
  4. 外观和操作:复选按钮通常是一个方形的控件,点击后内部会显示一个勾来表示选中状态。

示例代码(复选按钮):

QCheckBox *checkBox1 = new QCheckBox("Option A");
QCheckBox *checkBox2 = new QCheckBox("Option B");
QCheckBox *checkBox3 = new QCheckBox("Option C");

// 将checkBox1设置为默认选中
checkBox1->setChecked(true);

// 添加到布局中
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(checkBox1);
vbox->addWidget(checkBox2);
vbox->addWidget(checkBox3);

总结

  • QRadioButton(单选按钮)

    • 用于在一组选项中选择一个。
    • 组内的按钮是互斥的。
    • 适用于需要用户在多个选项中选择一个的场合。
  • QCheckBox(复选按钮)

    • 用于在多个选项中进行独立选择。
    • 每个按钮都是独立的,选中一个不会影响其他按钮的状态。
    • 适用于需要用户选择多个选项或启用/禁用某些设置的场合。

单选按钮 QRadioButton

Qt 中的单选按钮类是 QRadioButton

它是一个可以切换选中(checked)或未选中(unchecked)状态的单选按钮

单选按钮常用在 “多选一” 的场景,也就是说,在一组单选按钮中,一次只能选中一个单选按钮

比如性别中的 “男女” 二选一,学历中的 “博士/硕士/本科/其他” 四选一,等等。

选中状态

// 获取和设置单选按钮的选中状态
bool isChecked() const
void setChecked(bool)

可见,切换单选按钮的选中状态,有两种方式:

  • 通过鼠标点击实现
  • 在代码中使用 setChecked(bool) 来实现

自动排他

我们前面说过,单选按钮实现的是 “多选一”,因此单选按钮的该属性默认是使能的

// 获取和设置自动排他
bool autoExclusive() const
void setAutoExclusive(bool)

而对于多选按钮,也叫复选按钮-QCheckBox,通常的场景是用户选择一组按钮中的多个,因此该属性默认是禁能的。

综合以上,“多选一” 要满足以下两个条件:

把同一组的单选按钮,放在同一个布局中。不同的组的单选按钮,放在不同的布局中

单选按钮的 autoExclusive 属性设置为 true,单选按钮的该属性默认是使能的。可在右侧的属性按钮中看到,如下:

信号槽

按钮在按下和抬起的过程中,会发射多个信号。

// 单选按钮 QRadioButton 被点击时,会发出该信号
void clicked();

// 当单选按钮的选中状态发生改变时,会发射该信号
// 所谓状态改变,是指选中变为非选中,和非选中变为选中
void toggled(bool checked)

案例

复选框

Qt 中的复选按钮类是 QCheckBox

它和单选按钮很相似,单选按钮常用在 “多选一” 的场景,而复选按钮常用在 "多选多"的场景

比如喜欢的水果选项中,可以在 “苹果/桃/梨/橘子/香蕉” 中选择多个。

这两个是其父类 QAbstractButton 中的属性和方法,因此 QPushButtonQRadioButtonQCheckBox 都具有该属性

三态

单选按钮,有选中(Checked)和非选中(UnChecked)这两种状态;

而复选按钮可以有三种状态:

Qt::Checked 选中
Qt::Unchecked 非选中
Qt::PartiallyChecked 半选中,比如当一组复选按钮中只选择了部分时,可以设置其父项为半选状态,如下

可以设置复选按钮,是否支持三态,如下:

// 用于获取和设置是否支持三态
bool isTristate() const
void setTristate(bool y = true)

如果不支持三态,使用方法单选按钮一样,只有选中(Checked)和非选中(unchecked)两种状态,没有半选中状态( PartiallyChecked )

此时可以使用如下获取复选按钮是否选中:

// 获取和设置复选按钮是否选中:checked/unchecked
bool isChecked() const
void setChecked(bool)

如果支持三态,除了选中(Checked)和非选中(unchecked)两种状态,还有半选中状态( PartiallyChecked )

此时可以使用如下获取复选按钮的状态:

// 设置和获取复选按钮的状态
Qt::CheckState checkState() const
void setCheckState(Qt::CheckState state)

 信号槽

// 单选按钮 QRadioButton 被点击时,会发出该信号
void clicked();

// 当复选按钮的选中状态发生改变时,会发射该信号
// 所谓状态改变,是指在 Checked/UnChecked/PartiallyChecked 之间状态改变
void stateChanged(int state)

案例

代码

#include "SelectButton.h"

SelectButton::SelectButton(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::SelectButtonClass())
{
    QRadioButton/
    // 初始化
    ui->setupUi(this);
    ui->rbMan->setChecked(true);
    ui->rbDoctor->setChecked(true);
    ui->rbMan1->setChecked(true);
    ui->rbDoctor1->setChecked(true);

    // 使用QHBoxLayout
    connect(ui->rbMan, &QRadioButton::clicked, this, &SelectButton::on_QRadioButton_clicked);
    connect(ui->rbWoman, &QRadioButton::clicked, this, &SelectButton::on_QRadioButton_clicked);
    connect(ui->rbDoctor, &QRadioButton::clicked, this, &SelectButton::on_QRadioButton_clicked);
    connect(ui->rbMaster, &QRadioButton::clicked, this, &SelectButton::on_QRadioButton_clicked);
    connect(ui->rbBachelor, &QRadioButton::clicked, this, &SelectButton::on_QRadioButton_clicked);
    connect(ui->rbOther, &QRadioButton::clicked, this, &SelectButton::on_QRadioButton_clicked);
    on_QRadioButton_clicked();

    // 使用QGroupBox
    connect(ui->pbtOut, &QPushButton::clicked, this, [this]() {
        QString s;
        if (ui->rbMan1->isChecked())
            s = ui->rbMan1->text();
        else if (ui->rbWoman1->isChecked())
            s = ui->rbWoman1->text();

        if (ui->rbDoctor1->isChecked())
            s += ui->rbDoctor1->text();
        else if (ui->rbMaster1->isChecked())
            s += ui->rbMaster1->text();
        else if (ui->rbBachelor1->isChecked())
            s += ui->rbBachelor1->text();
        else
            s += ui->rbOther1->text();
        ui->lineEditOut->setText(s);
        });
QCheckBox///
    // 全选和全取消
    connect(ui->cbAll, &QCheckBox::stateChanged, this, [this]() {
        // 这里需要将“全选”按钮的三态设置为false
        // 也就是在鼠标点击时,只允许在checked和unchecked之间切换,不允许出现半选状态   
        Qt::CheckState state = ui->cbAll->checkState();
        if (state == Qt::Checked)
        {
            ui->cbApple->setChecked(true);
            ui->cbBanana->setChecked(true);
            ui->cbOrange->setChecked(true);
            ui->cbPear->setChecked(true);
            ui->cbWatermelon->setChecked(true);
        }
        else if (state == Qt::Unchecked)
        {
            ui->cbApple->setChecked(false);
            ui->cbBanana->setChecked(false);
            ui->cbOrange->setChecked(false);
            ui->cbPear->setChecked(false);
            ui->cbWatermelon->setChecked(false);
        }
        else
        {
        }
      
        });
     //局部选择
    connect(ui->cbApple, &QCheckBox::stateChanged, this, &SelectButton::onQCheckBoxChicked);
    connect(ui->cbBanana, &QCheckBox::stateChanged, this, &SelectButton::onQCheckBoxChicked);
    connect(ui->cbOrange, &QCheckBox::stateChanged, this, &SelectButton::onQCheckBoxChicked);
    connect(ui->cbPear, &QCheckBox::stateChanged, this, &SelectButton::onQCheckBoxChicked);
    connect(ui->cbWatermelon, &QCheckBox::stateChanged, this, &SelectButton::onQCheckBoxChicked);
}


SelectButton::~SelectButton()
{
    delete ui;
}

void SelectButton::on_QRadioButton_clicked()
{
    QString s;
    if (ui->rbMan->isChecked())
        s = ui->rbMan->text();
    else if(ui->rbWoman->isChecked())
        s = ui->rbWoman->text();

    if (ui->rbDoctor->isChecked())
        s += ui->rbDoctor->text();
    else if (ui->rbMaster->isChecked())
        s += ui->rbMaster->text();
    else if (ui->rbBachelor->isChecked())
        s += ui->rbBachelor->text();
    else
        s += ui->rbOther->text();
    ui->out->setText(s);
}

void SelectButton::onQCheckBoxChicked()
{
    
    //ui->cbAll->setTristate(true);
    QString s;
    bool appleChecked = ui->cbApple->isChecked();
    bool bananaChecked = ui->cbBanana->isChecked();
    bool orangeChecked =  ui->cbOrange->isChecked();
    bool pearChecked = ui->cbPear->isChecked();
    bool watermelonChecked = ui->cbWatermelon->isChecked();

    if (appleChecked && bananaChecked && orangeChecked && pearChecked && watermelonChecked)
        ui->cbAll->setCheckState(Qt::Checked);
    else if(!(appleChecked|| bananaChecked|| orangeChecked|| pearChecked|| watermelonChecked))
        ui->cbAll->setCheckState(Qt::Unchecked);
    else
        ui->cbAll->setCheckState(Qt::PartiallyChecked);

    if (appleChecked)
        s += ui->cbApple->text()+" ";
    if (bananaChecked)
        s += ui->cbBanana->text() + " ";
    if (orangeChecked)
        s += ui->cbOrange->text() + " ";
    if (pearChecked)
        s += ui->cbPear->text() + " ";
    if (watermelonChecked)
        s += ui->cbWatermelon->text() + " ";

    ui->lineEditOut_2->setText(s);
}

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐