我使用 atraitsui.api.Handler
来捕获和处理 a 的事件traitsui.api.View
,该视图包括一个按钮,其行为是从包含多个绘图的容器中删除一个绘图。当使用remove
按钮、pop()
调用方法并删除绘图时,将访问容器的组件列表。但是,视图不会重绘,因此该图似乎保留在原处。通过拖动角调整窗口大小将强制重绘,确认pop()
问题是:如何以编程方式强制重绘?
在我看来,这样做的正确位置是在处理程序的setattr
方法中,就在pop()
情节之后。
# 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})