【Qt】浅析QAction的事件触发机制 - triggered和toggled

本文介绍了QAction的基本概念,如何设置为可复选,以及QActionGroup如何影响triggered和toggled信号的行为,特别是关于互斥选择和setChecked功能的运用。
摘要由CSDN通过智能技术生成

QAction

QAction是什么?为什么要用它?

我们可以把对按钮的一次点击、对下拉菜单的一次选择抽象理解成对QAction的一次操作。使用QAction时,我们不需要关心绘制出来的UI是button还是menu还是啥。

它有一个我很喜欢的功能。就是,QAction能够配合QActionGroup使用,类似于元素与集合的关系,用来实现互斥选择的效果。就像这样:
源自Maya
开发中,我会偷懒把QAction对象命名为act。下文的示例代码也如此。

triggered和toggled是什么意思?两者什么时候触发?

我是真不会翻译这俩。但我可以类比。
大家可以把QAction想象成一把枪。
你点一次按钮,就是扣动一下扳机,就是trigger()一下,接着自动触发信号triggered
如果这是一把高科技赛博枪,你只需要扣动一次,它就可以一直打击,你再扣动一次,它就停止打击。那么,扣第一次触发信号toggled(true),扣第二次触发信号toggled(false)

QAction->setCheckable(true)

细心的你可能会留意到,信号triggered的定义是这样的:
在这里插入图片描述
它有一个bool类型的参数。但无论我们怎么点,参数checked一直是false(最后打印0)。

QToolButton* btn1 = new QToolButton(widget);
btn1->setDefaultAction(act1);

QToolButton* btn2 = new QToolButton(widget);
btn2->setDefaultAction(act2);

在这里插入图片描述
这是因为QAction默认不是checkable的。

一个按钮是否是checkable的区别在于,它是一个门铃还是一个吊灯开关。

默认按钮 - 门铃checkable按钮 - 开关

我们添加以下2行代码,将QAction设为checkable:

act1->setCheckable(true);
act2->setCheckable(true);
运行结果:

在这里插入图片描述

  1. 因为checkable的存在,toggled信号终于被触发了。
  2. toggled 优先 于triggered触发
  3. triggered的参数会根据 action当前的 checked状态传true或false。

QActionGroup

QActionGroup对triggered和toggled有什么影响?

QActionGroup默认IsExclusive() == true,排他的,单选的。

添加以下代码:

QActionGroup* group = new QActionGroup(widget);
group->addAction(act1);
group->addAction(act2);

运行,先点击按钮1,然后点击按钮2,再次点击按钮2:

在这里插入图片描述

可以看到,triggered的参数永远地变成true了。
因为QActionGroup的作用,我们每次只能启用一把枪。当act2被扣下时,act1就会被自动停用。对于已经启用的枪,我们再次点击,并不会使它停用;虽然状态上没有任何改变,但triggered信号会被发送第二次。

QActionGroup->setExclusive(false)

添加以下代码:

group->setExclusive(false);

效果和QActionGroup不存在时是一样的

在这里插入图片描述

setChecked函数与它们是什么关系?

既然group->setExclusive(false);和QActionGroup不存在时是一样的,那就没有研究下去的必要噜~

所以我们把这行代码删掉。

添加以下代码:

QPushButton* btn3 = new QPushButton("check btn1");
connect(btn3, &QPushButton::clicked, [=]() {act1->setChecked(true); });
QPushButton* btn4 = new QPushButton("check btn2");
connect(btn4, &QPushButton::clicked, [=]() {act2->setChecked(true); });
layout->addWidget(btn3);
layout->addWidget(btn4);

在这里插入图片描述
setChecked函数可以触发toggled,但不能触发triggered。triggered只能由trigger()函数或者用户点击触发。

20241028追加更新:如果一个action本身的checked状态已经是true,那么,执行setChecked(true)不会发生任何事情。

isChecked状态与信号是什么关系?

先改变状态,再触发信号。信号的bool checked参数表示的是改变后的状态。

附录:案例代码

QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
    : QMainWindow(parent)
{
    QWidget* widget = new QWidget(this);

    QAction* act1 = new QAction(widget);
    act1->setText("1");
    connect(act1, &QAction::triggered, this, [=](bool checked) {
        cout << "act1 triggered " << checked << endl; });
    connect(act1, &QAction::toggled, this, [=](bool checked) {
        cout << "act1 toggled " << checked << endl; });
   
    QAction* act2 = new QAction(widget);
    act2->setText("2");
    connect(act2, &QAction::triggered, this, [=](bool checked) {
        cout << "act2 triggered " << checked << endl; });
    connect(act2, &QAction::toggled, this, [=](bool checked) {
        cout << "act2 toggled " << checked << endl; });

    QToolButton* btn1 = new QToolButton(widget);
    btn1->setDefaultAction(act1);

    QToolButton* btn2 = new QToolButton(widget);
    btn2->setDefaultAction(act2);

    QVBoxLayout* layout = new QVBoxLayout(widget);
    layout->addWidget(btn1);
    layout->addWidget(btn2);

    setCentralWidget(widget);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值