QButtonGroup does not emit the 'ButtonToggled' signal when clicked
-
I am trying to display a simple group of two radio buttons, but for some reason the buttonToggled signal is not emitted when I click on the radio buttons.
Here's a code sample of what I am trying to do:class MainForm(QDialog): def __init__(self, parent = None): super(MainForm, self).__init__(parent) button_a = QRadioButton('Option A') button_b = QRadioButton('Option B') button_a.setChecked(True) button_group = QButtonGroup() button_group.addButton(button_a) button_group.addButton(button_b) button_group.buttonToggled.connect(self.on_button_signal) group_box = QGroupBox('Options') buttons_vbox = QVBoxLayout() buttons_vbox.addWidget(button_a) buttons_vbox.addWidget(button_b) group_box.setLayout(buttons_vbox) hbox = QHBoxLayout() hbox.addWidget(group_box) self.setLayout(hbox) @pyqtSlot(QAbstractButton, bool) def on_button_signal(self, button, checked): if checked: print('do something with {0}'.format(button.text())) def run_app(): app = QApplication(sys.argv) form = MainForm() form.show() app.exec_() if __name__ == '__main__': run_app()
The above code produces the following:
But the 'on_button_signal()' function never invoked when switching between options.
What am I doing wrong here?BTW, is there a way to emit signal only when the button is transitions from off to on?
This could spare the rather unneeded 'if checked' condition + spare the unneeded emitted signal when button transitions from on to off.
Thanks. -
I am no expert, just starting out managing someone else's PyQt application.
Looking through the code I have inherited, I see that it attaches each button's
button.toggled.connect(...)
instead of yourbutton_group.buttonToggled.connect(...)
It also does abuttonGroup.setExclusive(True)
. Do either of those help any?Plus no sign of any
@pyqtSlot
in code.Also I see the handlers all check state, no evidence of an "off-to-on-only" event.
P.S.
Docs forQButtonGroup
state:If a button is clicked, the buttonClicked() signal is emitted; for a checkable button in an exclusive group this means that the button has been checked.
and
This [buttonClicked()] signal is emitted when the given button is clicked. A button is clicked when it is first pressed and then released, when its shortcut key is typed, or when QAbstractButton::click() or QAbstractButton::animateClick() is programmatically called.
Apart from trying that signal instead of
toggled
, doesn't that imply signal only on button clicked to On, not to Off, just like you want?(BTW, I do assume you have verified the whole handler is not invoked, not just relying on the value of
checked
.)Finally --- and I may be way out of line on this --- your
button_group = QButtonGroup()
assigns just a local variable, which will have gone out of scope at end of__init__()
. If you tryself.button_group
instead, does that make any difference? -
Great!
For main problem:
Indeed, I didn't notice that QButtonGroup is the only object that has no live reference...
So, when the initializer ends, the object goes out of scope, and dies...
When I added it as a class member it did the trick.For the second:
toggled
also means that the handler will be called when button goes from 'off' to 'on' (I verified it), so, for example, when I click on 'option B' button, the handler is invoked twice: once for 'option A' button withchecked = False
, and second time for 'option B' button, withchecked = True
.
It's not a big deal, since like you see I can ignore the off-to-on signal by inspecting thechecked
, I was just wondering if there's a more elegant way to do that.Thanks you so much!
-
When I added it as a class member it did the trick.
I am happy that using
self.button_group = ...
has retained the reference for you as you need. In my code, all these widgets are stored intoself....
so they always stay in scope as long as the dialog does.[toggled] I was just wondering if there's a more elegant way to do that
I am indeed suggesting to you that there is a neater way to recognise switching a button On, but you don't seem to have tried my suggestion!
But, first you wrote:
BTW, is there a way to emit signal only when the button is transitions from off to on?
and later you write:
since like you see I can ignore the off-to-on signal by inspecting the checked
Those contradict! Do you wish to recognise Off->On or On->Off ?? :)
Assuming you want the most usual Off->On, replace
button_group.buttonToggled.connect(...)
bybutton_group.buttonClicked.connect(...)
.buttonClicked
is fired only when a button is switched On (fired only once, and passes nochecked
parameter since that would always beTrue
), whereasbuttonToggled
is called on both buttons for Off and On (and you have to examinechecked
). If you only want to know about Off->On, usebuttonClicked
.