Arranging widgets in ipywidgets interactive

Viewed 6324

I have this interactive graph code using ipywidgets; but not sure how to arragne the each variable inside the interactive function in widgets. the default layout is vertical. But I want to arrange them in horizontal way.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
plt.style.use('seaborn')
%config InlineBackend.figure_format = 'svg'
from ipywidgets import interactive,interact
#function to plot the different curves
def plot_function(u=1,v=2,w=3,x=4,y=5,z=6):
    time=np.arange(0,1,0.01)
    df=pd.DataFrame({"Y1":np.sin(time*u*2*np.pi),"y2":np.sin(time*v*2*np.pi),"y3":np.sin(time*w*2*np.pi),
                    "y4":np.sin(time*x*2*np.pi),"y5":np.sin(time*y*2*np.pi),"y6":np.sin(time*z*2*np.pi)})
    df.plot()
widget=interactive(plot_function,u=1,v=2,w=3,x=4,y=5,z=6)
widget

Output

3 Answers

interactive is restricted to fairly simple widget layouts. Have a look at the Flexbox options if you want to customize them some more.

One simple get around is to use the interactive call to generate and link your widgets and functions, then restructure the widgets inside a HBox. Then add a layout that tells the box to wrap at line ends. I added a couple more imports and three lines at the end to achieve this.

1) controls - an HBox of your input widgets.

2) The Output widget generated by the interactive call.

3) A VBox that wraps the two together.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
plt.style.use('seaborn')
%config InlineBackend.figure_format = 'svg'
#importing the necessary items from the Ipywidgets library 
from ipywidgets import interactive,interact, HBox, Layout,VBox
#function to plot the different curves
def plot_function(u=1,v=2,w=3,x=4,y=5,z=6):
    time=np.arange(0,1,0.01)
    df=pd.DataFrame({"Y1":np.sin(time*u*2*np.pi),"y2":np.sin(time*v*2*np.pi),"y3":np.sin(time*w*2*np.pi),
                    "y4":np.sin(time*x*2*np.pi),"y5":np.sin(time*y*2*np.pi),"y6":np.sin(time*z*2*np.pi)})
    df.plot()
widget=interactive(plot_function,u=1,v=2,w=3,x=4,y=5,z=6)
controls = HBox(widget.children[:-1], layout = Layout(flex_flow='row wrap'))
output = widget.children[-1]
display(VBox([controls, output]))

enter image description here

Hi this is the decorator which I am using instead of @interact:

def interact_delayed(_InteractFactory__interact_f=None, **kwargs):
    def patch(obj):
        if hasattr(obj.widget, 'layout'):
            obj.widget.layout = Layout(flex_flow='row wrap')
        for child in obj.widget.children:
            if hasattr(child, 'continuous_update'):
                child.continuous_update = False
        return obj
    if _InteractFactory__interact_f is None:
        def decorator(f):
            obj = interact(f, **kwargs)
            return patch(obj)
        return decorator
    else:
        obj = interact(_InteractFactory__interact_f, **kwargs)
        return patch(obj)

The patch function modifies default attributes of ipywidget object: applies the Layout suggested in the previous answer and also sets continuous_update to false which I found useful in my cases. The if-else branches takes care about decorator versus function use-case scenarios.

There is no way to arrange widgets by adding a parameter in "interact" or interactive.

Related