QActionGroup互斥不生效的问题

QActionGroup互斥不生效的问题

问题描述

我有一个单实例的QAction的集合actions_ 然后传入不同的QToolbar进行添加到不同的QToolbar实例中。其中使用到了QActionGroup将其中的单个QAction进行互斥的处理。当创建了多个Qtoolbar实例后,释放了其中一个实例,其他QToolbarQActionGroup互斥就不生效了。

之前的实现方式

        action_group_ = new QActionGroup(toolbar_);
        toolbar_->addAction(action_group_->addAction(actions_->get(action_id_t::CONTROL_MOUSE)));
        toolbar_->addAction(action_group_->addAction(actions_->get(action_id_t::CONTROL_MARKER)));
        toolbar_->addAction(action_group_->addAction(actions_->get(action_id_t::CONTROL_BANDPOWER)));
        actions_->get(action_id_t::CONTROL_MOUSE)->setChecked(true);
原因分析:

action_group_->addAction(actions_->get(action_id_t::CONTROL_MOUSE)) 会生成一个新的QAction取名为Temp_action,当QToolbar被释放的时候,action_group_也被释放了,同时Temp_action也被释放了,此时导致 actions_->get(action_id_t::CONTROL_MOUSE)) QAction中的互斥属性就被释放掉了。(具体的原因看后面的源码分析就可以理解了)

解决方案

在创建的时候就将QActionGroupaction创建出来,并用集合管理起来。问题就得到了解决。

//创建
control_group_ = new QActionGroup(this);
		id_2_action_group_[action_id_t::CONTROL_STRAT] = control_group_->addAction(get(action_id_t::CONTROL_STRAT));
		id_2_action_group_[action_id_t::CONTROL_PAUSE] = control_group_->addAction(get(action_id_t::CONTROL_PAUSE));

		action_group_ = new QActionGroup(this);
		id_2_action_group_[action_id_t::CONTROL_MOUSE] = action_group_->addAction(get(action_id_t::CONTROL_MOUSE));
		id_2_action_group_[action_id_t::CONTROL_MARKER] = action_group_->addAction(get(action_id_t::CONTROL_MARKER));
		id_2_action_group_[action_id_t::CONTROL_BANDPOWER] = action_group_->addAction(get(action_id_t::CONTROL_BANDPOWER));
		get(action_id_t::CONTROL_MOUSE)->setChecked(true);


//调用
toolbar_->addAction(actions_->get_group(action_id_t::CONTROL_MOUSE));
toolbar_->addAction(actions_->get_group(action_id_t::CONTROL_MARKER));
toolbar_->addAction(actions_->get_group(action_id_t::CONTROL_BANDPOWER));
源码分析,找到问题的本质

下面值列举了关键的代码用于分析:

//addAction方法
QAction *QActionGroup::addAction(QAction* a)
{
    Q_D(QActionGroup);
    if(!d->actions.contains(a)) {
        d->actions.append(a);
        QObject::connect(a, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
        //关键在于这一句,将传入进来的QAction的状态改变信号和新的槽函数_q_actionChanged进行连接
        //下面的代码我们就将分析 槽函数中的内容
        QObject::connect(a, SIGNAL(changed()), this, SLOT(_q_actionChanged()));
        QObject::connect(a, SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
    }
    if(!a->d_func()->forceDisabled) {
        a->setEnabled(d->enabled);
        a->d_func()->forceDisabled = false;
    }
    if(!a->d_func()->forceInvisible) {
        a->setVisible(d->visible);
        a->d_func()->forceInvisible = false;
    }
    if(a->isChecked())
        d->current = a;
    QActionGroup *oldGroup = a->d_func()->group;
    //并且从老的Group中移动出来,永远保存的只有最后创建出来的QActionGroup 对QAction的管理是有效的
    if(oldGroup != this) {
        if (oldGroup)
            oldGroup->removeAction(a);
        a->d_func()->group = this;
        a->d_func()->sendDataChanged();
    }
    return a;
}

//槽函数
//当某个QAction的的状态改变时候,槽函数就是将其他的checked状态设置成为false
//所以出现bug原因就被找到了
void QActionGroupPrivate::_q_actionChanged()
{
    Q_Q(QActionGroup);
    QAction *action = qobject_cast<QAction*>(q->sender());
    Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionChanged", "internal error");
    if (exclusionPolicy != QActionGroup::ExclusionPolicy::None) {
        if (action->isChecked()) {
            if (action != current) {
                if(current)
                    current->setChecked(false);
                current = action;
            }
        } else if (action == current) {
            current = 0;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值