Phillip M. Feldman
Phillip M. Feldman

Reputation: 546

How to use QSignalBlocker in Python?

I’m looking for either Python-specific documentation or--better yet--a sample snippet of Python code that shows how to use QSignalBlocker. Will be grateful for anything.

Upvotes: 4

Views: 3658

Answers (3)

Tyde
Tyde

Reputation: 343

Looking at the documation you can see, that the QSignalBlocker provides a __enter__ and a __exit__ function. On __enter__ the signals of the given object are blocked and on __exit__ the blocked state is set to the previous state. You can see this, when you look at the original Qt-documentation for QSignalBlocker and see the __enter__ function as the C++-constructor and the __exit__ function as the C++-destructor.

To leverage these function you can use the with-statement and block the signals effectively with this call:

with QSignalBlocker(self.double_spin_box) as blocker:
    self.double_spin_box.setValue(2.5)

This with-statement will translate this call to

blocker = QSignalBlocker(self.double_spin_box)
blocker.__enter__()
try:
    self.double_spin_box.setValue(2.5)
finally:
    blocker.__exit__()

Upvotes: 7

Phillip M. Feldman
Phillip M. Feldman

Reputation: 546

The above works, but I'm currently using an alternative mechanism that also works:

  self.blockSignals(True)
  self.field.clear()
  self.blockSignals(False)

Upvotes: 0

eyllanesc
eyllanesc

Reputation: 244202

The QSignalBlocker class has a simple behavior: When it is set to a QObject the emission of signals from the QObject is blocked, with the unblock() method the block is removed, with reblock() it is blocked again.

In the following example if the radiobutton is not checked then each time an item is selected from the QComboBox it will transmit the selected text to the QLabel through signals, if the radiobutton is checked then the signals will not be emitted so the QLabel will not show the text selected by the QComboBox:

from PyQt5 import QtCore, QtGui, QtWidgets


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        radiobutton = QtWidgets.QRadioButton("block/unblock")
        self.m_label = QtWidgets.QLabel()
        self.m_combobox = QtWidgets.QComboBox()
        self.m_combobox.addItems(
            [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
                "Sunday",
            ]
        )

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(radiobutton)
        lay.addWidget(self.m_label)
        lay.addWidget(self.m_combobox)

        self.m_blocker = QtCore.QSignalBlocker(self.m_combobox)
        self.m_blocker.unblock()
        self.m_combobox.currentTextChanged.connect(self.m_label.setText)
        radiobutton.toggled.connect(self.on_toggled)

    @QtCore.pyqtSlot(bool)
    def on_toggled(self, state):
        if state:
            self.m_blocker.reblock()
        else:
            self.m_blocker.unblock()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

The same logic can be done with the blockSignals() method of the QObject's:

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        radiobutton = QtWidgets.QRadioButton("block/unblock")
        self.m_label = QtWidgets.QLabel()
        self.m_combobox = QtWidgets.QComboBox()
        self.m_combobox.addItems(
            [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
                "Sunday",
            ]
        )

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(radiobutton)
        lay.addWidget(self.m_label)
        lay.addWidget(self.m_combobox)

        radiobutton.toggled.connect(self.m_combobox.blockSignals)
        self.m_combobox.currentTextChanged.connect(self.m_label.setText)

Upvotes: 1

Related Questions