Hello, everyone! I'm having some trouble with callback in my PyQt5 app.

I want more than one callback available to an object, but defining any subsequent callback in an object overwrites all previous callbacks. However, the callbacks are decorated, which seems to be messing with things. How should I define object-level callbacks, so I can use self in them?

In the following example, which you can run on any computer with Python 3.x and PyQt5.11.x, a spinbox is hooked up to two valueChanged callbacks. These are called A and C. However, the second callback C never triggers, and a third callback D triggers instead. D should not trigger.

Qt Code:
  1. from PyQt5 import QtWidgets
  2. from PyQt5.QtCore import pyqtSlot
  3.  
  4.  
  5. def silenceCallbacks(*elements):
  6. """Silence events for the duration of a callback. Mostly skipped for this reproduction."""
  7. def silenceCallbacksOf(callback):
  8. def silencedCallback(self, *args, **kwargs):
  9. callback(self, *args, **kwargs)
  10. return silencedCallback
  11. return silenceCallbacksOf
  12.  
  13.  
  14. @pyqtSlot(int)
  15. @silenceCallbacks()
  16. def callbackA(px: int):
  17. #correctly called
  18. print('got A', px)
  19.  
  20. @pyqtSlot(int) #this overwrites the last three functions
  21. @silenceCallbacks()
  22. def callbackB(px: int):
  23. #correctly not called
  24. print('got B', px)
  25.  
  26.  
  27. class RecordingSettings(QtWidgets.QDialog):
  28. @pyqtSlot(int)
  29. @silenceCallbacks()
  30. def callbackC(self, px: int):
  31. #incorrectly not called
  32. print('got C', px)
  33.  
  34. @pyqtSlot(int) #this overwrites the previous pyqtSlot-decorated function
  35. @silenceCallbacks()
  36. def callbackD(self, px: int):
  37. #incorrectly called
  38. print('got D', px)
  39.  
  40.  
  41. def __init__(self, window):
  42. super().__init__()
  43.  
  44. spin = QtWidgets.QSpinBox()
  45.  
  46. spin.valueChanged.connect(callbackA)
  47. spin.valueChanged.connect(self.callbackC)
  48.  
  49. layout = QtWidgets.QVBoxLayout()
  50. layout.addWidget(spin)
  51. self.setLayout(layout)
  52. self.show()
  53.  
  54.  
  55.  
  56. app = QtWidgets.QApplication([])
  57. recSettingsWindow = RecordingSettings(app)
  58. recSettingsWindow.show()
  59. app.exec_()
To copy to clipboard, switch view to plain text mode 

If anyone's got any ideas, that'd be much appreciated. Thank you.