2014-12-05 1 views
1

Я использовал traitsui.api.Handler, чтобы поймать и обработать события для traitsui.api.View, который включает в себя кнопку, поведение которой заключается в удалении графика из контейнера, содержащего несколько графиков. Доступ к списку компонентов контейнера осуществляется при использовании кнопки remove, вызывается метод pop(), и участок удаляется. Тем не менее, представление не перерисовывается, и поэтому график, по-видимому, остается на месте. Изменение размера окна с помощью перетаскивания угла заставит перерисовать, подтверждая pop()Могу ли я принудительно разрешить Контейнер перерисовывать из обработчика traitsui?

Вопрос: Как я могу принудительно выполнить программный перерисовывание?

Мне кажется, что подходящее место для этого было бы в методе Handler's 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}) 

ответ

3

Самый простой способ получить эту работу, чтобы позвонить invalidate_and_redraw на вашем участке контейнера после извлечения участка. В этом случае вы можете изменить свой призыв к pop выглядеть примерно так:

plots_container = info.ui.context['pgrid'].plots_container 
plots_container.components.pop() 
plots_container.invalidate_and_redraw() 

Longer обсуждение:

В идеале, это будет обрабатываться Чако. Частично проблема заключается в том, что контейнер не был предназначен для изменения списка components. Вместо этого (я предполагаю) намерение состояло в том, чтобы вызвать пользователя plots_container.remove по элементу в списке components.

Это, как указано, , что, похоже, не работает. Оказывается, что remove аннулирует текущее состояние, но не запрашивает перерисовку. (Мое предположение заключается в том, что chaco/enable не автоматически перерисовывается, так как в строке может быть много операций с отказом от кеша, например, если вы должны удалить все графики из этого контейнера, вам нужно будет только перерисовать после всех вызовов . remove, а не после того, как каждый из них)

Так на самом деле использовать этот альтернативный метод, можно было бы написать что-то вроде:

plot = plots_container.components[-1] 
plots_container.remove(plot) 
plots_container.request_redraw() 
+0

Отлично. Я рад отметить это как ответ, он работает как шарм. Не возражаете, если я спрошу, где вы получаете документы? В документации очень мало информации о включении, поэтому его небольшая часть поисковой системы показывает наилучшие способы работы с API. – OYRM

+0

К сожалению, мой ответ основан на опыте и быстро взгляните на исходный код. Документации действительно немного не хватает здесь. –