Question

I am making a UI which involves embedding a Mayavi view in a wx frame with controls, and I'm running into some problems. To strip down the issue, I've put together a working script which is a combination of their wx embedding and red ball picker examples; my project is a more sophisticated version of this.

I have two questions:

  1. If the user selects a different number of balls, I'd like to clear the figure and re-draw with a new set of balls. However, from what I've gathered from googling, I'd need to reset the picker after the clf() call. The similar examples I've seen use the @on_trait_change decorator for the scene.activated trait, but I'm not sure how to do this when the scene is not activated, but merely updated.
  2. If the user selects a different ball color, I'd like to simply change the color in-place without re-creating the scene. It appears that I can do so by using the set method of the glyph's mlab_source, and I imagine that it would be best to call this using @on_trait_change. However, I don't know how to best connect the wx triggering event to a trait type that allows for @on_trait_change to be fired.

Thanks in advance.

P.S. I wanted to post this instead at the enthought mailing list but the site appears to be down and has been for some time. Anyone noticed the same?

Was it helpful?

Solution

I'm not sure I understand what the problem is. To get your code working it seems like a simple matter of calling the scene in the wx notifiers (which you have a reference to) and making the necessary adjustments. Like so:

def on_number_of_balls_selected():
  n = self.get_selected_ball_number()
  clear_figure()
  #mlab.clf(scene = self.mayavi_view.scene.mayavi_scene )

  # make some new points
  new_points = somehow_make_some_new_points(n)
  mlab.points3d( new_points, scene=self.mayavi_view.scene.mayavi_scene )

  # reattach the picker
  picker = self.mayavi_view.figure.on_mouse_pick(self.mayavi_view.picker_callback)

and so on, these calls might not be put together quite right but this is the basic idea.

The solution is not conceptually different if you were using traitsui, but I'm curious why if you're going to use traitsui to render the mayavi scene, why not also use it to show the enums in the GUI? This is really the intended use case of traitsui (for simple applications). If you have a reason why not -- great, there are certainly many use cases where traitsui is not the best tool and working with the toolkit (or enaml which I haven't really given a fair try personally) gives you greater flexibility to control the layout and offer a broader array of widgets. But traitsui provides a slightly nicer solution to this problem of providing notifications for when the user changes some numbers in the GUI (though you stil have to write the listeners).

Edit: It turns out the tvtk picker detaches itself on mlab.clf (reasonable) and prevents new pickers listening to the same events from being reattached (not so reasonable). I believe this is a bug in tvtk, and I could not isolate it in 30 minutes. Therefore for now I suggest to avoid mlab.clf altogether (I have adjusted the code above to reflect this). Instead, call the remove method of each source module which will cause the source to delete itself from the scene:

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

After that, the picker will be disconnected, but you can create the new objects and then reattach the picker to the new objects by calling on_mouse_pick as normally.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top