Description
Problem
When using interact
with several figures, output is typically cleared when the first change arrives, and so you can "see it drawing as it goes". Here's a simple snippet:
from matplotlib import pyplot
import ipywidgets
from IPython.display import display
import numpy
def long_plots(x, y, z):
pts = numpy.arange(x)
pyplot.figure()
pyplot.plot(pts, pts * y)
pyplot.figure()
pyplot.plot(pts, pts * z)
display(ipywidgets.interact(long_plots, x=(2, 10), y=(-3, 3), z=(-5, 5)))
As you move the sliders, you'll see the two plots being created. It's snappy on Chrome, but a bit slower in VSCode. It results in some flashing which is not desirable.
Proposed Solution
Why not double-buffer with a second Output
instance, so that the one that is being displayed only receives one change? i.e. in interaction.py, replace this code:
with self.out:
if self.clear_output:
clear_output(wait=True)
for widget in self.kwargs_widgets:
value = widget.get_interact_value()
self.kwargs[widget._kwarg] = value
self.result = self.f(**self.kwargs)
show_inline_matplotlib_plots()
if self.auto_display and self.result is not None:
display(self.result)
with something like this:
buffer = Output()
buffer.clear_output()
with buffer:
for widget in self.kwargs_widgets:
value = widget.get_interact_value()
self.kwargs[widget._kwarg] = value
self.result = self.f(**self.kwargs)
show_inline_matplotlib_plots()
# Note: Not sure how to handle this
# if self.auto_display and self.result is not None:
# display(self.result)
with self.out:
if self.clear_output:
clear_output(wait=True)
display(buffer)
(I acknowledge I'm not proposing a complete solution here; just trying to show the idea. I've prototyped it by extracting the code from interact_output
and modifying it and the concept seems sound.)
Is there a reason this isn't done?