I'm trying to use ginput
to register clicks on a map, and wanted to add action buttons using matplotlib widgets. In the following code, I can pass back the value of action to the main code by declaring it a global
. If I click on the map, action=0, if I click on the button, action=1, as desired.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
class Index:
def test(self, event):
global action
action=1
# fake data
x=np.arange(30)
y=x**2
fig,ax=plt.subplots()
ax.plot(x,y)
callback = Index()
buttonname=['test']
colors=['white']
idx=[0.2]
bax,buttons={},{}
# set up list of buttons.
for i,col,button in zip(idx,colors,buttonname):
bax[button] = plt.axes([0.92, i, 0.07, 0.07])
buttons[button] = Button(bax[button],button,color=col,hovercolor='green')
buttons[button].on_clicked(getattr(callback,button))
# register click on plot
while True:
pts=plt.ginput(1)
plt.pause(0.5)
print("action is ",action)
action=0 # reset
But my confusion is, if I take the exact same code and place it in a def block, the value of action is no longer passed back, action
is always zero.
def subtest():
class Index:
def test(self, event):
global action
action=1
# fake data
action=0
x=np.arange(30)
y=x**2
fig,ax=plt.subplots()
ax.plot(x,y)
callback = Index()
buttonname=['test']
colors=['white']
idx=[0.2]
bax,buttons={},{}
# set up list of buttons.
for i,col,button in zip(idx,colors,buttonname):
bax[button] = plt.axes([0.92, i, 0.07, 0.07])
buttons[button] = Button(bax[button],button,color=col,hovercolor='green')
buttons[button].on_clicked(getattr(callback,button))
# register click on plot
while True:
pts=plt.ginput(1)
plt.pause(0.5)
print("action is ",action)
action=0 # reset
res=subtest()
I'm very confused as to why this happens. I tried moving the class definition out into the main code but that didn't help. I'm happy for any kind of solution (e.g. passing action through an argument, which I have not understood how to do with widgets), as I think that the use of global
is often frowned apon. But also a global
-based solution is fine.
action
inside subtest
is local to subtest, while action
inside Index.test
is global. Either declare action
global in subtest
, or use nonlocal
in Index.test
.
(I suspect there may be better solutions without globals, but since I'm not familiar with the GUI toolkit I'll leave that to someone else.)