Search code examples
pythonpyqtpyqt5signals

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.


Solution

  • 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)