python - Can I force my enable Container to redraw from a traitsui Handler? -
i have employed traitsui.api.handler
catch , handle events traitsui.api.view
, view includes button, behavior remove plot container containing multiple plots. container's components list accessed when remove
button used, pop()
method called, , plot removed. however, view not redraw, , plot appears remain in place. resizing window through dragging corner force redraw, confirming pop()
the question is: how can force redraw programmatically ?
it seems me right place in handler's setattr
method, after pop()
-ing plot.
# major library imports numpy import linspace scipy.special import jn # enthought library imports enable.api import container, componenteditor traits.api import hastraits, instance, button, int, str traitsui.api import item, hgroup, view, vsplit, uitem, instanceeditor, handler # chaco imports chaco.api import arrayplotdata, gridcontainer, plot # =============================================================================== # attributes use plot view. size = (1000, 800) color_palette = [ (0.65098039, 0.80784314, 0.89019608, 1.0), (0.12156863, 0.47058824, 0.70588235, 1.0), (0.69803922, 0.8745098, 0.54117647, 1.0), (0.2, 0.62745098, 0.17254902, 1.0), (0.98431373, 0.60392157, 0.6, 1.0), (0.89019608, 0.10196078, 0.10980392, 1.0), (0.99215686, 0.74901961, 0.43529412, 1.0), (1., 0.49803922, 0., 1.0), (0.79215686, 0.69803922, 0.83921569, 1.0), ] class instanceuitem(uitem): """convenience class including instance in view""" style = str('custom') editor = instance(instanceeditor, ()) # =============================================================================== # # managerhandler view's handler #=============================================================================== class managerhandler(handler): def setattr(self, info, object, name, value): handler.setattr(self, info, object, name, value) info.ui.context['pgrid'].plots_container.components.pop() #at point, container not redraw, , so, while no longer #contains last plot in components collection, plot still # visible # =============================================================================== # # plotsgrid class used demo #=============================================================================== class plotsgrid(hastraits): plots_container = instance(container) rows = int(3) cols = int(3) #=============================================================================== # # create plots, adapted chaco gridcontainer demo #=============================================================================== def _plots_container_default(self): # create gridcontainer hold of our plots container = gridcontainer(padding=20, fill_padding=true, bgcolor="lightgray", use_backbuffer=true, shape=(self.rows, self.cols), spacing=(20, 20)) # create initial series of data x = linspace(-5, 15.0, 100) pd = arrayplotdata(index=x) # plot bessel functions , add plots our container in range(self.rows * self.cols): pd.set_data("y" + str(i), jn(i, x)) plot = plot(pd) plot.plot(("index", "y" + str(i)), color=tuple(color_palette[i]), line_width=2.0, bgcolor="white", border_visible=true) container.add(plot) return container # =============================================================================== # # controls hastraits provides button used wire in desired behavior #=============================================================================== class controls(hastraits): rem_plot = button("remove ...") def _rem_plot_changed(self): print "rem plot changed" # =============================================================================== # # manager_view provides view , defines layout #=============================================================================== manager_view = view( vsplit( hgroup( item('controls.rem_plot', height=32) ), item('pgrid.plots_container', editor=componenteditor(size=size), show_label=false), show_border=true ), handler=managerhandler(), resizable=true ) grid = plotsgrid() ctrl = controls() if __name__ == "__main__": ctrl.configure_traits(view=manager_view, context={'pgrid': grid, 'controls': ctrl})
the simplest way working call invalidate_and_redraw
on plot container after popping plot. in case, modify call pop
like:
plots_container = info.ui.context['pgrid'].plots_container plots_container.components.pop() plots_container.invalidate_and_redraw()
longer discussion:
ideally, handled chaco. part of problem container wasn't designed have components
list modified directly. instead, (i'm guessing) intention have user call plots_container.remove
on item in components
list.
that said, that doesn't seem work either. turns out remove
invalidates current state, doesn't request redraw. (my guess chaco/enable doesn't automatically redraw since there may many cache-invalidating operations in row; e.g. if remove plots container, you'd want redraw after calls remove
, not after each one.)
so use alternative method, write like:
plot = plots_container.components[-1] plots_container.remove(plot) plots_container.request_redraw()
Comments
Post a Comment