Я пытаюсь иметь 3 отдельных окна (фигуры), содержащие разные вещи. Я не собираюсь заранее точно знать, каким будет содержимое каждого из них, потому что эти окна - просто контейнеры. Но в широком смысле одно или несколько окон будут содержать графики данных, а одно окно будет содержать большинство (может быть, все) контроллеров для этих (интерактивных) графиков.
По сути, я пишу код-оболочку вокруг matplotlib, чтобы пользователи могли воспользоваться предопределенными шаблонами для отображения данных. Будет несколько предопределенных форм, и со временем будут добавлены новые.
Итак, я делаю что-то вроде этого:
class DefaultViewer:
def __init__(self, **kwargs):
self.graph_win = ContainerWindow(label='Some Graph')
self.ctrl_win = ContainerWindow(label='Controller elements')
# other code here....
def set_controllers(self):
self.sld_gstart = ElementControlSlider(self.ctrl_win.grid, xpos=0, label='Gate Start')
self.sld_gwidth = ElementControlSlider(self.ctrl_win.grid, xpos=1, label='Gate Width')
self.sld_saturation = ElementControlSlider(self.ctrl_win.grid, xpos=2, label='Saturation')
(Позже может появиться некоторый класс OtherViewer, который может использовать разные окна).
Окно контейнера. Он предоставляет некоторые полезные значения по умолчанию, в противном случае он также примет все, что передано для переопределения этих значений по умолчанию:
class ContainerWindow:
""" Contains the ElementControlers in a single window, and/or the graphs etc. """
def __init__(self, nrows=5, ncols=12, width_pad=0.4, heigh_pad=0.4, figsize=(12,12), label='A ContainerWindow' ,**kwargs):
# Uses the default parameters or the value provided if any
self.nrows = nrows
self.ncols = ncols
self.figsize = figsize
self.figure= plt.figure(label, figsize=figsize)
self.grid = plt.GridSpec(nrows, ncols, wspace=width_pad, hspace=heigh_pad, figure=self.figure)
Наконец ElementControlSlider:
class ElementControlSlider:
def __init__(self, grid, xpos=1,ypos=1, width=5, label='' , val_min=0, val_max=100, init_val=50, text_box_pos=(0,0),**kwargs):
self.ax_slider = plt.subplot(grid[xpos, ypos:ypos+width], label=label)
self.ax_text = plt.subplot(grid[xpos, ypos + width + 1], label=label)
self.slider = Slider(self.ax_slider, label, val_min, val_max, valinit=init_val)
self.slider.valtext.set_visible(False)
self.textbox = TextBox(self.ax_text, '', self.slider.val)
def update_text(self, value):
try:
val = int(value)
assert(val > 0)
except (ValueError, AssertionError):
self.textbox.set_val(str(self.slider.val))
else:
self.slider.set_val(val)
Мое понимание matplotlib, похоже, неверно. По сути, я создаю разные фигуры в каждом ContainerWindow (self.figure = plt.figure (....). Они получают разные метки, и если я отлаживаю в Pycharm, они действительно разные объекты - пока все хорошо.
Затем я создаю в каждом окне сетку (GridSpec (...)). Таким образом, у каждого окна есть своя сетка (в которую я собираюсь поместить свои графики и / или элементы контроллера). Каждой сетке я передаю ссылку на рисунок этого окна.
Затем, когда я создаю экземпляр элемента контроллера, я передаю ему ссылку на сетку, в которую он будет помещен (сетка, которая имеет ссылку на свою родительскую фигуру, например, WindowContainer, в котором я ожидаю, что он будет находиться ).
Однако, если я изменю порядок объявления моего ContainerWindow, тогда ползунки будут назначены на неправильную фигуру / окно.
Почему мои ссылки на объекты оказываются неверными? Как сделать так, чтобы независимо от того, в каком порядке я создавал окна, мои ползунки оказались в правильном виде?