I am using Qt in C++ instead of Python, but I hope these information could help.
Unfortunately there seems no direct solution to this problem at present. The "exclusive" property of QActionGroup
limits the feature of selection, which ensures at least and only one action is selected at any one time (but at the begining of the program, you have to manually set one of actions to be "checked")
Here is part of the source code, you can see how it works on QAction
if the "exclusive" property is installed by 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 );
}
}
}
(Ref: http://qt-x11-free.sourcearchive.com/documentation/3.3./classQActionGroup_182fe3a5a859e6397a4ba05be346d894.html older version of Qt, but the concept is the same)
To solve the problem, at least you have two options:
Still use
QActionGroup
and add anotherQAction
"None is selected" (or something similar) in your list. This might be the most proper option since it considers "no selection" as a selection and can exploit the feature ofQActionGroup
.Not to use
QActionGroup
. In this case, you have to manually implement the exclusiveness. Once aQAction
is selected,emit
a signal that sends a pointerQAction*
to aSLOT
which compares the present selection with the previous one from buffer (default = 0), if difference occurs, deselect (usesetCheck(false)
) the previous one and assign the present selection to buffer.
It's just a rough idea, but still feasible if you really need the feature
[EDIT]: Though I am not sure about the exact functionality you want, I wrote some C++ code here FYR. Notice that this is just a demo of the "ostensible" feature of the exclusively checkable QActions and the ability of unchecking any checked one.The according responses of checked/unchecked state still need further implementation.
TheClass.h:
class TheClass
{
Q_OBJECT
......
public slots:
void action0Checked();
void action1Checked();
void action2Checked();
void compareChecked(QAction *newChecked);
signals:
void selectedID(QAction *newChecked);
private:
QAction *buffer;
QList<QAction*> actionList;
}
TheClass.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;
}
}