'Is there any way to bind a differnt click handler to QPushButton in PyQt5?

I have a QPushbutton:

btn = QPushButton("Click me")
btn.clicked.connect(lambda: print("one"))

Later in my program, I want to rebind its click handler, I tried to achieve this by calling connect again:

btn.clicked.connect(lambda: print("two"))

I expected to see that the console only prints two, but actually it printed both one and two. In other words, I actually bound two click handlers to the button.

How can I rebind the click handler?



Solution 1:[1]

Signals and slots in Qt are observer pattern (pub-sub) implementation, many objects can subscribe to same signal and subscribe many times. And they can unsubscribe with disconnect function.

from PyQt5 import QtWidgets, QtCore

if __name__ == "__main__":
    app = QtWidgets.QApplication([])

    def handler1():
        print("one")

    def handler2():
        print("two")

    button = QtWidgets.QPushButton("test")
    button.clicked.connect(handler1)
    button.show()

    def change_handler():
        print("change_handler")
        button.clicked.disconnect(handler1)
        button.clicked.connect(handler2)

    QtCore.QTimer.singleShot(2000, change_handler)

    app.exec()

In case of lambda you can only disconnect all subscribers at once with disconnect() (without arguments), which is fine for button case.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1