PDA

View Full Version : QAction::setEnabled() Not Working as Expected



pmwalk
22nd March 2012, 03:16
I've run into an odd problem when trying to disable a QAction menu item object. There's no good way to paste a small working example, but the code of note is as follows:



ui.button_send->setEnabled(true);
std::cout << ui.actionConnect->isEnabled() << std::endl;
ui.actionConnect->setEnabled(false);
std::cout << ui.actionConnect->isEnabled() << std::endl;


I am trying to have a button that I can click to connect to a simulator (details not important). When the simulator boots up, it sends a signal back that calls the function with this code. The print lines read "1" then "0" as expected, indicating that the actionConnect menu item is no longer enabled. However, I can still click on the meny item after this occurs, and it triggers another redundant attempt to connect (i.e., it is not disabled at all). The button_send button in ui, however, does get enabled properly (after being disabled on startup).

I found a few places through online searching that indicate there may be bugs with QAction::setEnabled(), but nothing concrete. Is there anywhere else I should look to figure out what might be the problem? I know this is vague, so I'm mostly just looking for ideas or hints. Thanks in advance.

ChrisW67
22nd March 2012, 04:04
Is your simulator relinquishing control to the Qt event loop quickly, or taking a long time without processing events?

d_stranz
22nd March 2012, 05:27
In the code you pasted, you show two different GUI objects, "button_send" (line 1) and "actionConnect" (lines 2 - 4), and the code never disables the "button_send" action. Is this a typo? If not, that's probably the reason why you can still execute the command.

pmwalk
22nd March 2012, 08:16
Is your simulator relinquishing control to the Qt event loop quickly, or taking a long time without processing events?

I don't think that's the problem. I tried it with a push button instead of a QAction menu item, and that one disables and grays out fine. Every other way of doing it has no problem, just with the QAction item.

Anyway, for the time being, I've replaced it with a button. It doesn't need to be in the menu for my application, but I'm still curious to figure out the problem.


In the code you pasted, you show two different GUI objects, "button_send" (line 1) and "actionConnect" (lines 2 - 4), and the code never disables the "button_send" action. Is this a typo? If not, that's probably the reason why you can still execute the command.

The first line was actually just included in the code I pasted to show an example of something that did work. Lines 2-4 are the important ones. When I disable button_send later it disables fine.

MarekR22
22nd March 2012, 09:34
Apparently you are misunderstanding something. After you add action to some object you shouldn't control this object, don't change it: enable state, title, icon and so on.
All this state changes should be done by QAction. Note that not all buttons are handling QActions, QToolButton does.

wysota
22nd March 2012, 14:54
If you want an action and a button to do the same thing then replace your QPushButton instance with QToolButton and use QToolButton::setDefaultAction() passing it the action from the menu. Then the menu entry and the button will always be synchronized when you disable or otherwise change properties of the action object.

pmwalk
24th March 2012, 07:20
Apparently you are misunderstanding something. After you add action to some object you shouldn't control this object, don't change it: enable state, title, icon and so on.
All this state changes should be done by QAction. Note that not all buttons are handling QActions, QToolButton does.

The menu bar item is a QAction though, and completely separate from the button. The Button and the QAction both had the same effect on the simulator side, but from Qt they send out different signals (although they shouldn't and won't when I do similar things in the future- see below). My point is that QAction.setEnabled(false) doesn't seem to be working. If I delete the button completely and just have the QAction menu item, it still doesn't work.


If you want an action and a button to do the same thing then replace your QPushButton instance with QToolButton and use QToolButton::setDefaultAction() passing it the action from the menu. Then the menu entry and the button will always be synchronized when you disable or otherwise change properties of the action object.

Yea that makes sense- I knew that and had just forgotten. I'm still learning all the ins and outs of Qt so sometimes things get forgotten :).