Open drs378 opened 2 years ago
I am also seeing this behaviour with ipympl 0.9.2 and matplotlib 3.6.2.: The plot does not get put into the Output widget.
This breaks the top search result for "ipywidgets plot": https://kapernikov.com/ipywidgets-with-matplotlib/
@drs378 : Did you check 0.5.8 was the last version that worked or did you just happen to have it at hand?
Just want to confirm the same problem for me with ipympl 0.9.2 and matplotlib 3.6.2
I take that the issue is the ordering of the plot relative to the buttons?
This behavior changed slightly as part of https://github.com/matplotlib/ipympl/pull/343. While unfortunate that this changed it was necessary as part of fixing the longstanding and important issue of plot. The core of what's happening here is that the plot is being displayed before the output widget has an opportunity to capture it. (sidenote @martinRenou is that actually expected, it would maybe be nice if output widgets captured the plots).
Fortunately there is a workaround - which is to be more explicit about what you are doing. You can read more about it in the docs here: https://matplotlib.org/ipympl/examples/full-example.html#interactions-with-other-widgets-and-layouting
But the short of it is:
plt.subplots
call in an ioff
blockfig.canvas
into the widget layout.Combining those, you should make the final lines like so:
with plt.ioff():
fig, ax = plt.subplots()
ax.plot(x,y)
display(ipy.HBox([fig.canvas,ipy.VBox([b1,b2])]))
Thanks, @ianhi ! That works as expected. I have a separate but related question. I used to be able to create a pop-out browser window of a figure via the following code, but now it doesn't work anymore and I'm guessing a similar small change is necessary with the final two output lines. Thanks in advance.
def _popout_fig(fig, name="name"):
buf = BytesIO()
fig.savefig(buf, format="png")
fig_size_pix = fig.get_size_inches() * fig.dpi
s = '<script type="text/Javascript">'
s += f'var win = window.open("", "{name}", "toolbar=no, location=no, status=no, menubar=no, '\
f'scrollbars=yes, resizable=yes, width={1.12*fig_size_pix[0]}, height={1.12*fig_size_pix[1]}, '\
'top="+(screen.height-400)+", left="+(screen.width-840));' # This part sets where it shows on screen
s += f'win.document.title = "{name}";'
s += 'win.document.body.innerHTML = \''
img = base64.b64encode(buf.getbuffer()).decode('ascii')
s += f'<img src="data:image/png;base64,{img}"/>'
s += '\';'
s += '</script>'
with widgets.Output():
IPython.display.display(IPython.display.HTML(s)) # noqa
Never mind, I solved it. I still need a widgets.Output object that's a child of the original displayed widget, and then use it in place of the with widgets.Output():
above.
All my concerns are now resolved.
Describe the issue
I built a small GUI within a notebook and had two figures in an ipywidgets HBox object. the latest version of ipympl made it so I could not have both figures in an HBox and generally disrupted the formatting of the object. I was able to fix the issue by reverting both matplotlib and the ipympl versions.
a short script that generates the broken output is as follows
Versions
(working version)
(broken version)