Search code examples
pythonmatplotlibjupyter-notebookipywidgets

Button widget adds new plots instead of replacing the old one


I have a function using widgets that is working just fine, but the slider is a little hard to move in small steps.

I want to add buttons to go forwards or backwards one step on click. This is implemented in the code below. My problem is that when I call back the original function myplot from inside on_button_, it draws everything again, but I only want the updated scatter plot.

I've experimented with plt.close('all') and plt.show() as you can see.

My problem -I think- is that I can't find the right place to put them.

import ipywidgets as widgets
from ipywidgets import interact, interact_manual, Button, HBox, fixed

@interact 

step = 0.1
def myplot(
            x=(0.3, 3, step), 
            y=(0,8,1)):
  
        

    ###############
    def on_button_next(b):
        plt.close('all')
        myplot(x+step, y=y)

    def on_button_prev(b):
        plt.close('all')
        myplot(x-step, y=y)

    button_next = Button(description='x+')
    button_prev = Button(description='x-')
    ############################

    if x>0.3 :  
        plt.figure(figsize=(9,7))
        ax1 = plt.subplot()
        ax1.scatter(x, y, marker='*', s=300)
        ax1.set_xlim(0,2)
        ax1.set_ylim(0,8)


        ##### buttons. 
        display(HBox([button_prev, button_next]))
        button_next.on_click(on_button_next)
        button_prev.on_click(on_button_prev)
        ################

    return plt.show()

Solution

  • Solved by removing plt.show() and plt.close() and writing instead display(fig) and clear_output()

    from IPython.display import clear_output
    
    step=0.1
    
    @interact 
    
    def myplot(
                x=(0.3, 3, step), 
                y=(0,5,1)):
    
            
    
    #         ##############
        def on_button_next(b):
            clear_output()
            myplot(x+step, y=y)
        def on_button_prev(b):
            clear_output()
            myplot(x-step, y=y)
    
        button_next = Button(description='x+')
        button_prev = Button(description='x-')
    
        ##############
        if x>0.3 :  
            
            #buttons
            
            display(HBox([button_prev, button_next]))
            button_next.on_click(on_button_next)
            button_prev.on_click(on_button_prev)
            ##
            
            fig = plt.figure()
            plt.scatter(x, y, marker='*', s=300)
            plt.xlim(0.3,2)
            plt.ylim(0,8)
            plt.close()
            display(fig)