Updating `GridspecLayout` on click
See original GitHub issueHi, thanks to the developers for putting this thing together – it looks awesome!
I have a usage question though. I’m trying to make a layout of plots with NxM rows and columns. Right now I’m prototyping with just buttons. The idea is to be able to expand the layout (i.e. add new panels) by clicking on one of the buttons.
Here’s a class I have so far (probably not the best way, but anyway).
import ipywidgets as ipyW
from IPython.display import display
class PlotGrid():
def __init__(self, nn):
self.panels = []
for n in range(nn):
self.createNewPanel(n=n)
self.redraw()
def createNewPanel(self, **kwargs):
button = ipyW.Button(description='Button {}'.format(kwargs['n']),
layout=ipyW.Layout(height='auto', width='auto'))
button.on_click(self.appendGrid)
self.panels.append(button)
def appendGrid(self, status):
self.createNewPanel(n=len(self.panels))
self.redraw()
def redraw(self):
ncols = int(np.sqrt(len(self.panels)))
nrows = int(np.ceil(len(self.panels) / ncols))
self.grid = ipyW.GridspecLayout(nrows, ncols)
n = 0
for i in range(self.grid.n_rows):
for j in range(self.grid.n_columns):
if (n < len(self.panels)):
self.grid[i, j] = self.panels[n]
n += 1
def show(self):
display(self.grid)
So when I run this:
plotgrid = PlotGrid(12)
plotgrid.show()
it does what it should: fills in the .grid object with panels. When I click on the button the appendGrid function is indeed called, and it does append the new panels to the grid as it should. But for some reason the result is not displayed in the cell: it just remains the same. If I later update the cell by running plotgrid.show() again – it draws the new extended .grid as it should.
So I think I’m not understanding something fundamental with how the display function works and Jupyter handles the events.
These are the versions of the relevant packages I got through conda:
ipykernel 5.2.0 py38h23f93f0_1 conda-forge
ipython 7.13.0 py38h32f6830_2 conda-forge
jupyterlab 2.1.0 py_0 conda-forge
widgetsnbextension 3.5.1 py38_0 conda-forge
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (3 by maintainers)

Top Related StackOverflow Question
Hey @haykh your solution is probably the best approach, so congrats on figuring that out! I think the issue was that
displaydoesn’t work quite the way you’d expect. If you change the objects that went into a display they will not immediately update. Instead you need to explicitly update the display (you can get a reference to it by providing an id). Like so:cell 1:
Will have
aas the output cell 2:now cell 1’s output will be
b.You can read more about this here, here and here. I would particularly recommend implementing the
_ipython_display_method on your class.In your working example you are circumventing having to do something like that by using the widget update system. The
Boxobject listens for changes to it’schildrenand updates any views of itself whenever it’s children changes. Unfortunately that is the best solution as my example above withupdate_displaydoesn’t actually work with ipywidgets, which is a known bug https://github.com/jupyter-widgets/ipywidgets/issues/1180Yup it does!
Your approach is totally reasonable, it’s the “ipywidgets” solution whereas I was suggesting the “matplotlib” solution. More about this in this unmerged PR updating ipympl examples: https://github.com/matplotlib/ipympl/pull/244
I see you’re using
display(fig). Beware thatdisplay(fig)anddisplay(fig.canvas)are actually pretty different. The former will display a static png, while the latter will create an interactive plot so you can can pan, zoom, and easily update the contents.