Home > front end >  python, create multiple matplotlib button widgets in for loop
python, create multiple matplotlib button widgets in for loop

Time:12-07

I need to generate a variable number (total) of button widgets in matplotlib and have each one store a different number in the variable, var.

import matplotlib.pyplot as plt
from matplotlib.widgets import Button as BT

total = 4

class Index:
    ind = 0
        
    def plot_pick(self, event):
        var=event
        print(var)

ax_chooseplot={}
chooseplot_BT={}
callback=Index()

for i in range(0,total):
    loc=0.95-i*0.03
    ax_chooseplot[i] = plt.axes([loc-0.002, 0.87, 0.02, 0.03])
    chooseplot_BT[i] = BT(ax_chooseplot[i], '')
    chooseplot_BT[i].on_clicked(callback.plot_pick(i))         
    
plt.show()

This code prints i sequentially then on pressing any button:

TypeError: 'NoneType' object is not callable

It seems like the function "plot_pick" is being called during the for loop and then the value of i is being discarded?

I've seen this issue addressed for tkinter buttons but I've been unable to apply those answers to matplotlib embedded buttons. Is there an easy way to solve this?

CodePudding user response:

The issue comes from the way you are passing the i argument to your plot_pick function. Passing it directly to your function won't work. A possible alternative is to use functools.partial. You can find below an example where I use functools.partial to print the index of the button that was clicked on:

import matplotlib.pyplot as plt
from matplotlib.widgets import Button as BT
import functools

total = 4

class Index:
    ind = 0

    def plot_pick(self,i, event):
        print('Button ' str(i))
        

ax_chooseplot={}
chooseplot_BT={}
callback=Index()


for i in range(0,total):
    loc=0.95-i*0.03
    ax_chooseplot[i] = plt.axes([loc-0.002, 0.87, 0.02, 0.03])
    chooseplot_BT[i] = BT(ax_chooseplot[i], str(i))
    chooseplot_BT[i].on_clicked(functools.partial(callback.plot_pick,i))  
   
    
plt.show()
  • Related