Itamar Katz
Itamar Katz

Reputation: 9655

Creating matplotlib widget callback inside a function

I am using python 2.7 on Windows. I have a function which creates a figure with a CheckButtons widget, and it also includes the definition of the button's callback. When I call the function once, everything is OK, but when I call it more than once, the buttons stops responding, as follows:

My guess is that is has to do with the scope of the callback, but I couldn't pinpoint the problem using trial-and-error.

Sample code:

import matplotlib.pyplot as plt
from matplotlib.widgets import CheckButtons

def create_button():
    plt.subplots() # or: plt.figure()
    rax = plt.axes([0.2, 0.2, 0.2, 0.2])
    check = CheckButtons(rax, ['on'], [True])
    def callback(label):
        check.labels[0].set_text('on' if check.lines[0][0].get_visible() else 'off')
        plt.draw()
    check.on_clicked(callback)

create_button()
#create_button() # uncomment to reproduce problem
plt.show() 

Upvotes: 2

Views: 715

Answers (2)

PRD
PRD

Reputation: 29

I think also if you return check at the end of the function this will work to keep the button alive on exit.

Upvotes: 1

Itamar Katz
Itamar Katz

Reputation: 9655

It turns out the problem was that the CheckButtons instance created inside the function no longer exists after the function returns.

The solution I came up with was to keep a list in the scope where the function is called (I used a static variable in a class), and append the instance to this list from within the function. This way the CheckButtons instance still exists when the function exits. In order for that list to not grow more than needed, I also wrote a function which deletes the corresponding instance from the list, and registered this function as a callback for the event of the figure being closed by the user.

I will be happy to hear comments on my solution, or suggestions for more Pythonish solution, if such a solution exists.

Upvotes: 3

Related Questions