enthought / mayavi

3D visualization of scientific data in Python
http://docs.enthought.com/mayavi/mayavi/
Other
1.28k stars 282 forks source link

Unable to reattatch on_mouse_pick to figure #1204

Open PrzemyslawW13 opened 1 year ago

PrzemyslawW13 commented 1 year ago

Windows 7/64bit and Windows 10/64bit mayavi 4.8.1 python 3.8.9 Basically the same issue as in this very old subject.

def clear_figure(self):
  for child in self.scene.mayavi_scene.children:
    child.remove()

The solution of calling remove method on all children of the scene kinda works but not really. It will let you attach the picker, but it will add it multiple times - it removes the connection, but not the callback itself.

I think the issue comes from conditionals in callback_added method, or more precisely from callbacks dictionaries that don't get cleared after removing their connection in callback_removed method (if not type in self._picker_callback_nbs:, if not self._mouse_mvt_callback_nb:, if not button in self._mouse_press_callback_nbs:, if not button in self._mouse_release_callback_nbs:). I managed to fix that issue by clearing the callbacks dictionaries in "mouse_pick_dispatcher.py". I did it by modifying the callback_removed method (I marked added lines with #mod):

def callback_removed(self, item):
        """ Clean up the unnecessary VTK callbacks.
        """
        callback, type, button = item

        # If the picker is no longer needed, clean up its observers.
        if not [t for c, t, b in self.callbacks if t == type]:
            picker = self._active_pickers[type]
            picker.remove_observer(self._picker_callback_nbs[type])
            del self._active_pickers[type]
            del self._picker_callback_nbs[type] #mod

        # If there are no longer callbacks on the button, clean up
        # the corresponding observers.
        if not [b for c, t, b in self.callbacks if b == button]:
            self.scene.scene.interactor.remove_observer(
                    self._mouse_press_callback_nbs[button])
            del self._mouse_press_callback_nbs[button] #mod
            self.scene.scene.interactor.remove_observer(
                    self._mouse_release_callback_nbs[button])
            del self._mouse_release_callback_nbs[button] #mod
        if len(self.callbacks) == 0 and self._mouse_mvt_callback_nb:
            self.scene.scene.interactor.remove_observer(
                            self._mouse_mvt_callback_nb)
            self._mouse_mvt_callback_nb = 0

I couldn't find similar solution posted anywhere, so I thought to post it here. I'm new to github so I dunno how/where to propose a fix. I hope someone will find it useful :).