The fun part is that I just tried to simulate a similar scenario with a dummy “filter” whose layout contains just a single button, and the crash did not occur. Then, when I started to add more elements, the error occurred in the same way.
This will not cause a crash:
class DummyFilter(CustomFilter):
filter_name = "Dummy Filter"
short_description = "Just a dummy"
tooltip = "Just a dummy"
def __init__(self):
super().__init__()
self.filter_name = DummyFilter.filter_name
self.short_description = DummyFilter.short_description
self.tooltip = DummyFilter.tooltip
def createUI(self, parent):
parametersFormLayout = super().createUI(parent)
UI = CustomFilterUI(parent = parametersFormLayout)
dummy_btn = qt.QPushButton("Dummy btn")
UI.widgets.append(dummy_btn)
UI.addWidgetWithToolTip(dummy_btn,{"tip":"Dummy btn clicked"})
dummy_btn.connect('clicked(bool)', self.on_dummy_btn)
self.UI = UI
return UI
def on_dummy_btn(self):
print("Dummy btn clicked")
def execute(self, ui = None):
super().execute(ui = ui)
While this will:
class DummyFilter(CustomFilter):
filter_name = "Dummy Filter"
short_description = "Just a dummy"
tooltip = "Just a dummy"
def __init__(self):
super().__init__()
self.filter_name = DummyFilter.filter_name
self.short_description = DummyFilter.short_description
self.tooltip = DummyFilter.tooltip
def createUI(self, parent):
parametersFormLayout = super().createUI(parent)
UI = CustomFilterUI(parent = parametersFormLayout)
dummy_btn = qt.QPushButton("Dummy btn")
UI.widgets.append(dummy_btn)
UI.addWidgetWithToolTip(dummy_btn,{"tip":"Dummy btn clicked"})
dummy_btn.connect('clicked(bool)', self.on_dummy_btn)
# clip widget
UI.clip_widget = ctk.ctkRangeWidget()
UI.widgets.append(UI.clip_widget)
UI.addWidgetWithToolTipAndLabel(UI.clip_widget,{"tip":"Values outside the 'clip range' will be set to the given 'clip range'",
"label":"Input clip range"})
UI.clip_widget.enabled = False
UI.clip_widget.connect("valuesChanged(double,double)",
lambda min,max, widget=UI.clip_widget, name = 'clip': self.onRangeChanged(name,widget,min,max))
self.UI = UI
return UI
def on_dummy_btn(self):
print("Dummy btn clicked")
def onRangeChanged(self, name, widget, min_val, max_val):
if name == "clip":
print(f"clip: {min_val} - {max_val}")
def execute(self, ui = None):
super().execute(ui = ui)
Then I noticed, that in my duck-taped code, I forgot to implement storing of the connections made on-flight. Oddly, this will not result in a crush - if there is only one widget on the layout.
So… to make the previously mentioned destroy function work properly, one should make sure that every connection is stored in the widgetConnections list.