pythonpython-3.xpyqt5qdockwidgetqaction

QAction.isChecked() always False, even after it has been set to True at init


I have a PyQt5 app that has QDockWidgets on it's main window, and I have a menu that contain these dockwidgets listed. Whenever I click on a menu item, I want that widget to be closed or opened depending on whether the menu item is checked or not when I click it.

I check the menu items at init like this:

self.stream_action = QAction('Stream')
self.stream_action.setCheckable(True)
self.stream_action.setChecked(True)
self.stream_action.triggered.connect(self.show_hide_widget)

I do the same for the rest of them, and when the GUI starts it looks like this:

enter image description here

So when I click on one of them we jump to the show_hide_widget function, that looks like this:

def show_hide_widget(self):
    widget_id = self.sender().text()
    if self.sender().isChecked():
        self.sender().setChecked(False)
        if widget_id == 'Stream':
            self.dock_stream.close()
    else:
        self.sender().setChecked(True)
        if widget_id == 'Stream':
            self.dock_stream.show()

But self.sender().isChecked() gives me False, why is that?


Solution

  • Whenever a checkable action is triggered, its checked state is toggled too.

    Comment out that functions, try to trigger the action again, and you'll see: when you see it the first time, it is checked, but by clicking it you're also toggling its state (even if you don't see the result because it immediately disappears). Open the menu again and you'll that the action is now unchecked, trigger it again and your function will work as you thought it would.

    This obviously means that you should not set the check state of the action in the show_hide_widget function.

    Also, consider implementing the triggered checked argument, which is a better choice than calling self.sender().

    def show_hide_widget(self, state):
        print(state)