Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 858
Phillip M. Feldman Avatar asked Nov 03 '25 21:11

Phillip M. Feldman


2 Answers

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__()
like image 98
Tyde Avatar answered Nov 06 '25 12:11

Tyde


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)
like image 28
eyllanesc Avatar answered Nov 06 '25 11:11

eyllanesc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!