I am coding a program where the user can interactively modify a plot. I am using 3 mpl_connect
functions (key_press_event
button_press_event
button_release_event
) plus 4 text boxes (mwidgets.TextBox
).
Each time I type text to the text boxes, the process is slow and I think it is because when I click and write on a text box, it needlessly triggers the 3 "mpl connections" (key_press_event
button_press_event
button_release_event
).
The 3 text boxes are outside the "axes object" and so I wonder if there is a way to limit the "mpl conections" to within the axis of interest only. That is, instead of coding the following:
cid1 = figure.canvas.mpl_connect('key_press_event', onPressKey)
cid2 = figure.canvas.mpl_connect('button_press_event', onPressButton)
cid3 = figure.canvas.mpl_connect('button_release_event', onReleaseButton)
to code something like (note the substitution of canvas
for axes
):
cid1 = figure.axes.mpl_connect('key_press_event', onPressKey)
cid2 = figure.axes.mpl_connect('button_press_event', onPressButton)
cid3 = figure.axes.mpl_connect('button_release_event', onReleaseButton)
Is there some workaround?
Any comment is welcome!
Have a look at this simplistic example, and watch what the print
statements return:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.widgets import TextBox
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.2)
t = np.arange(-2.0, 2.0, 0.001)
s = t ** 2
initial_text = "t ** 2"
l, = plt.plot(t, s, lw=2)
def submit(text):
ydata = eval(text)
l.set_ydata(ydata)
ax.set_ylim(np.min(ydata), np.max(ydata))
plt.draw()
def onPressKey(event):
print('you pressed key {0} in ax {1}'.format( event.key, event.inaxes ))
if event.inaxes in [ax]:
print("in ax")
elif event.inaxes in [fig.axes[1]]:
print("in cid1")
else:
print("outside")
axbox = plt.axes([0.1, 0.05, 0.8, 0.075])
text_box = TextBox(axbox, 'Evaluate', initial=initial_text)
text_box.on_submit(submit)
fig.canvas.mpl_connect('key_press_event', onPressKey)
plt.show()
If you hover your mouse over the "plot region" (i.e. ax
, or fig.axes[0]
), every key you press will trigger the default keybindings (i.s. s triggers the save dialog).
The onPressKey(event)
handler can already be used to decide what to do with this input, since it is aware of event.inaxes
, i.e. where your mouse was during the key_press_event
.
Note however, that once you click inside the TextBox
widget, it will capture your input (i.e. s gets written in there, no save dialog is triggered).
If you now move your mouse outside of the texbox, the onPressKey(event)
handler will still let you know that your mouse was within ax
during text input (or perhaps "outside"), but this does not change the fact that the TextBox
widget still captures your input, until you e.g. press enter.
The short answer: you don't want to connect the key_press_event
to a specific axis, but rather want to let the onPressKey(event)
handler, well handle it. Each keystroke should register as one key_press_event, so this will likely not be the culprit in your case (well unless your actual code is e.g. set up to do some expensive calculations on e.g. key e down, and you have forgotten to click inside the TextBox
first.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With