I have employed a traitsui.api.Handler
to catch and handle events for a traitsui.api.View
, that view includes a button, whose behavior is to remove a plot from a container containing multiple plots. The container's components list is accessed when the remove
button is used, the pop()
method is called, and the plot is removed. However, the view does not redraw, and so that plot appears to remain in place. Resizing with window through dragging a corner will force the redraw, confirming the pop()
The question is: How can I force the redraw programmatically ?
It seems to me that the right place to do so would be in the Handler's setattr
method, just after pop()
-ing the plot.
# Major library imports
from numpy import linspace
from scipy.special import jn
# Enthought library imports
from enable.api import Container, ComponentEditor
from traits.api import HasTraits, Instance, Button, Int, Str
from traitsui.api import Item, HGroup, View, VSplit, UItem, InstanceEditor, Handler
# Chaco imports
from chaco.api import ArrayPlotData, GridContainer, Plot
# ===============================================================================
# Attributes to use for the 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 for including an Instance in a View"""
style = Str('custom')
editor = Instance(InstanceEditor, ())
# ===============================================================================
# # ManagerHandler will be the 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 this point, the container does not redraw, and so, while it no longer
#contains the last plot in its components collection, that plot is still
# visible
# ===============================================================================
# # PlotsGrid class that is used by the demo
#===============================================================================
class PlotsGrid(HasTraits):
plots_container = Instance(Container)
rows = Int(3)
cols = Int(3)
#===============================================================================
# # Create the plots, this is adapted from the chaco GridContainer demo
#===============================================================================
def _plots_container_default(self):
# Create a GridContainer to hold all of our plots
container = GridContainer(padding=20, fill_padding=True,
bgcolor="lightgray", use_backbuffer=True,
shape=(self.rows, self.cols), spacing=(20, 20))
# Create the initial series of data
x = linspace(-5, 15.0, 100)
pd = ArrayPlotData(index=x)
# Plot some bessel functions and add the plots to our container
for i 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 a button used to wire in the desired behavior
#===============================================================================
class Controls(HasTraits):
rem_plot = Button("remove ...")
def _rem_plot_changed(self):
print "rem plot changed"
# ===============================================================================
# # manager_view provides the View and defines its 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})