From ae2a9bcfb530fe9f45cd08f67e51f33bbffd1430 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Fri, 2 May 2014 15:37:39 +0100
Subject: [PATCH] Property listeners are removed when corresponding widgets are
 destroyed.

---
 fsl/props/build.py   |  9 +++++++--
 fsl/props/widgets.py | 21 +++++++++++++--------
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/fsl/props/build.py b/fsl/props/build.py
index addfc5e9a..4020f041b 100644
--- a/fsl/props/build.py
+++ b/fsl/props/build.py
@@ -651,10 +651,15 @@ def _prepareEvents(hasProps, propGui):
     onChange()
 
     # add a callback listener to every property
+    lName = 'build_py_WhenEvent'
     for propObj, propName in zip(propObjs, propNames):
-
-        lName = 'build_py_WhenEvent'
         propObj.addListener(hasProps, lName, onChange)
+
+    def removeListeners(ev):
+        for propObj, propName in zip(propObjs, propNames):
+            propObj.removeListener(hasProps, lName)
+
+    propGui.topLevel.Bind(wx.EVT_WINDOW_DESTROY, removeListeners)
  
 
 def buildGUI(parent,
diff --git a/fsl/props/widgets.py b/fsl/props/widgets.py
index d5c528c6a..08c29b4a8 100644
--- a/fsl/props/widgets.py
+++ b/fsl/props/widgets.py
@@ -111,11 +111,7 @@ def _propBind(hasProps, propObj, propVal, guiObj, evType, labelMap=None):
         is changed. Updates the property value.
         """
 
-        # TODO remove property value listener when GUI object is destroyed
-        try:
-            value = guiObj.GetValue()
-        except:
-            raise
+        value = guiObj.GetValue()
 
         if propVal.get() == value: return
 
@@ -128,6 +124,11 @@ def _propBind(hasProps, propObj, propVal, guiObj, evType, labelMap=None):
     for ev in evType: guiObj.Bind(ev, _propUpdate)
     propVal.addListener(listenerName, _guiUpdate)
 
+    guiObj.Bind(wx.EVT_WINDOW_DESTROY,
+                lambda ev: propVal.removeListener(listenerName))
+
+    
+
 
 def _setupValidation(widget, hasProps, propObj, propVal):
     """
@@ -160,9 +161,13 @@ def _setupValidation(widget, hasProps, propObj, propVal):
     # associated with multiple variables, and we don't want
     # the widgets associated with those other variables to
     # change background.
-    propVal.addListener(
-        'widgets_py_ChangeBG_{}'.format(id(widget)),
-        _changeBGOnValidate)
+    lName = 'widgets_py_ChangeBG_{}'.format(id(widget))
+    propVal.addListener(lName, _changeBGOnValidate)
+
+    # And ensure that the listener is
+    # removed when the widget is destroyed
+    widget.Bind(wx.EVT_WINDOW_DESTROY,
+                lambda ev: propVal.removeListener(lName))
 
     # Validate the initial property value,
     # so the background is appropriately set
-- 
GitLab