Qt 如何强制QActionGroup允许取消选中?

Qt 如何强制QActionGroup允许取消选中?,qt,pyside,Qt,Pyside,我在QActionGroup中有许多操作,因为我希望它们是独占的(如果选中了一个,那么所有其他操作都应该被取消选中)。但是,我也希望能够取消选中所有选项。此时,如果我选中action1,然后再次单击按钮,它将不会取消选中,取消选中的唯一方法是单击其他操作。简而言之,QActionGroup确保只检查了1个操作-我想确保只检查了1个或0个操作。有解决办法吗 我使用PySead,但是我也比较满意C++中的Qt,所以C++中的一个解决方案会很好,我确信我可以转换它。 代码(不是很有帮助,但我会在相关情

我在QActionGroup中有许多操作,因为我希望它们是独占的(如果选中了一个,那么所有其他操作都应该被取消选中)。但是,我也希望能够取消选中所有选项。此时,如果我选中action1,然后再次单击按钮,它将不会取消选中,取消选中的唯一方法是单击其他操作。简而言之,QActionGroup确保只检查了1个操作-我想确保只检查了1个或0个操作。有解决办法吗

我使用PySead,但是我也比较满意C++中的Qt,所以C++中的一个解决方案会很好,我确信我可以转换它。 代码(不是很有帮助,但我会在相关情况下发布)

所有操作都是可检查的(在QT设计器中设置)

相关的:
有一个类似于此的bug报告,但是设计者已经决定不改变任何东西:

我用C++中的Qt代替Python,但是我希望这些信息可以帮助。 不幸的是,目前似乎没有直接解决这个问题的办法。
QActionGroup
的“exclusive”属性限制了选择功能,确保在任何时候至少且仅选择一个操作(但在程序开始时,您必须手动设置一个要“检查”的操作)

这是源代码的一部分,如果
QActionGroup

{
    if ( !isExclusive() )
      return;
    QAction* s = (QAction*) sender();
    if ( b ) {
      if ( s != d->selected ) {
          d->selected = s;
          for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
            if ( it.current()->isToggleAction() && it.current() != s )
                it.current()->setOn( FALSE );
          }
          emit activated();
          emit selected( s );
      } else if ( !s->isToggleAction() ) {
          emit activated();
      }
    } else {
      if ( s == d->selected ) {
          // at least one has to be selected
          s->setOn( TRUE );
      }
    }
}
class.cpp:

TheClass::TheClass()
{
    QMenuBar *menuBar = new QMenuBar(this); 
    buffer = 0;

    QMenu *menu = menuBar->addMenu("ActionList");
    actionList.append(menu->addAction("Action0"));
    actionList.append(menu->addAction("Action1"));
    actionList.append(menu->addAction("Action2"));

    for (int i=0; i<3; i++) {
        actionList[i]->setCheckable(true);
    }

    connect(actionList[0], SIGNAL(triggered()), this, SLOT(action0Checked()));
    connect(actionList[1], SIGNAL(triggered()), this, SLOT(action1Checked()));
    connect(actionList[2], SIGNAL(triggered()), this, SLOT(action2Checked()));
    connect(this, SIGNAL(selectedID(QAction*)), this, SLOT(compareChecked(QAction*)));
}

void TheClass::action0Checked()
{
    if (actionList[0]->isChecked()) {
        // do sth.

        emit selectedID(actionList[0]);
    }
}

void TheClass::action1Checked()
{
    if (actionList[1]->isChecked()) {
        // do sth.

        emit selectedID(actionList[1]);
    }
}

void TheClass::action2Checked()
{
    if (actionList[2]->isChecked()) {
        // do sth.

        emit selectedID(actionList[2]);
    }
}

void TheClass::compareChecked(QAction *newChecked)
{
    if (newChecked != buffer) {
        if (buffer != 0)
            buffer->setChecked(false);

        buffer = newChecked;
    }
}
TheClass::TheClass()
{
QMenuBar*menuBar=新的QMenuBar(此);
缓冲区=0;
QMenu*menu=menuBar->addMenu(“操作列表”);
actionList.append(菜单->添加操作(“Action0”);
附加(菜单->添加操作(“操作1”);
附加(菜单->添加操作(“操作2”);
for(int i=0;isetCheckable(true);
}
连接(actionList[0],信号(triggered()),此,插槽(action0Checked());
连接(actionList[1],信号(triggered()),此,插槽(action1Checked());
连接(actionList[2],信号(triggered()),此,插槽(action2Checked());
连接(此,信号(选择EDID(QAction*)),此,插槽(比较选中(QAction*));
}
作废类::操作0已检查()
{
如果(actionList[0]->isChecked()){
//做某事。
发出selectedID(操作列表[0]);
}
}
作废类::action1Checked()
{
如果(actionList[1]->isChecked()){
//做某事。
发出selectedID(操作列表[1]);
}
}
作废类::action2Checked()
{
如果(actionList[2]->isChecked()){
//做某事。
发出selectedID(操作列表[2]);
}
}
void类::compareChecked(QAction*newChecked)
{
if(newChecked!=缓冲区){
如果(缓冲区!=0)
buffer->setChecked(false);
buffer=newChecked;
}
}

我知道已经好几年了。但我遇到了同样的问题,并在Qt论坛上找到了一个。它基本上是这样做的:

connect(action_group, &QActionGroup::triggered, [](QAction* action) {
    static QAction* lastAction = nullptr;
    if (action == lastAction)
    {
      action->setChecked(false);
      lastAction = nullptr;
    }
    else
      lastAction = action;
  });
希望它对其他人的未来搜索有用

编辑:正如@Joe所建议的,这可以通过以下代码进一步改进:

connect(action_group, &QActionGroup::triggered, [lastAction = static_cast<QAction *>(nullptr)](QAction* action) mutable {
    if (action == lastAction)
    {
      action->setChecked(false);
      lastAction = nullptr;
    }
    else
      lastAction = action;
  });
connect(action\u group,&QActionGroup::triggered,[lastAction=static\u cast(nullptr)](QAction*action)可变{
if(action==lastAction)
{
操作->设置检查(假);
lastAction=nullptr;
}
其他的
最后行动=行动;
});

感谢您的帮助-明天我将尝试第二种方法(因为“无”选项在我的应用程序中不合适)。不客气。如果您在尝试第二个帖子时遇到任何问题,请随时更新帖子。感谢您提供的代码示例-它非常有用。我的新类正在按预期工作。再次感谢!这可以通过捕获
lastAction=static_cast(nullptr)进一步改进
而是将lambda标记为
可变的
。否则,窗口的多个实例将导致问题。我不理解部分
lastAction=static\u cast(nullptr)
它应该放在第二行而不是
static QAction*lastAction=nullptr;
还是应该放在第六行而不是
lastAction=nullptr;
?还是应该同时放在这两行?它应该放在lambda的捕获列表中并替换静态变量。
connect(action_group, &QActionGroup::triggered, [](QAction* action) {
    static QAction* lastAction = nullptr;
    if (action == lastAction)
    {
      action->setChecked(false);
      lastAction = nullptr;
    }
    else
      lastAction = action;
  });
connect(action_group, &QActionGroup::triggered, [lastAction = static_cast<QAction *>(nullptr)](QAction* action) mutable {
    if (action == lastAction)
    {
      action->setChecked(false);
      lastAction = nullptr;
    }
    else
      lastAction = action;
  });