Skip to content

Commit 843542d

Browse files
Impaler343daniilS
andcommitted
Added API note, enhanced gallery example, applied fix
Co-authored-by: daniilS <daniil.soloviev@gmail.com>
1 parent 4edc215 commit 843542d

File tree

4 files changed

+47
-21
lines changed

4 files changed

+47
-21
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Default focus behavior of ``FigureCanvasTkAgg``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Previously, when a `.FigureCanvasTkAgg` object was created, focus was set to the
5+
canvas by default. Now, focus is not set anymore. If focus is desired on the canvas,
6+
it can be set explicitly after creation using the ``focus_set()`` method of Tkinter
7+
widgets.
8+
9+
See :doc:`../../../gallery/user_interfaces/embedding_in_tk_sgskip` for an example of
10+
focus-setting in an embedded Matplotlib figure in a Tkinter application.

galleries/examples/user_interfaces/embedding_in_tk_sgskip.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,7 @@ def update_frequency(new_val):
6262
toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
6363
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=True)
6464

65+
# Explicitly set focus to canvas for it to receive key press events
66+
canvas.get_tk_widget().focus_set()
67+
6568
tkinter.mainloop()

lib/matplotlib/backends/_backend_tk.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,6 @@ def filter_destroy(event):
255255
CloseEvent("close_event", self)._process()
256256
filter_destroy_id = root.bind("<Destroy>", filter_destroy, "+")
257257

258-
self._tkcanvas.focus_set()
259-
260258
self._rubberband_rect_black = None
261259
self._rubberband_rect_white = None
262260

lib/matplotlib/tests/test_backend_tk.py

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -215,33 +215,48 @@ def test_save_figure_return():
215215
print("success")
216216

217217

218-
@_isolated_tk_test(success_count=1)
218+
@_isolated_tk_test(success_count=3)
219219
def test_canvas_focus():
220+
import matplotlib
220221
import tkinter as tk
221222
import matplotlib.pyplot as plt
222-
success = []
223+
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
224+
matplotlib.use('Tkagg')
223225

224-
def check_focus():
225-
tkcanvas = fig.canvas.get_tk_widget()
226-
# Give the plot window time to appear
227-
if not tkcanvas.winfo_viewable():
228-
tkcanvas.wait_visibility()
229-
# Make sure the canvas has the focus, so that it's able to receive
230-
# keyboard events.
231-
if tkcanvas.focus_lastfor() == tkcanvas:
232-
success.append(True)
233-
plt.close()
234-
root.destroy()
226+
def assert_focus(widget, expected_focus_state):
227+
if not widget.winfo_viewable():
228+
widget.wait_visibility()
229+
230+
has_focus = (widget.focus_get() == widget)
231+
232+
if has_focus == expected_focus_state:
233+
print("success")
235234

236235
root = tk.Tk()
237236
fig = plt.figure()
238-
plt.plot([1, 2, 3])
239-
root.after(0, plt.show)
240-
root.after(100, check_focus)
241-
root.mainloop()
237+
canvas = FigureCanvasTkAgg(fig, root)
238+
tkcanvas = canvas.get_tk_widget()
239+
tkcanvas.pack()
242240

243-
if success:
244-
print("success")
241+
# Test 1: Default Behavior (No Focus Stealing)
242+
assert_focus(tkcanvas, expected_focus_state=False)
243+
244+
# Test 2: Explicit Focus
245+
tkcanvas.focus_force()
246+
assert_focus(tkcanvas, expected_focus_state=True)
247+
248+
plt.close(fig)
249+
root.destroy()
250+
251+
# Test 3: Showing the plot should grab focus
252+
fig2 = plt.figure()
253+
tkcanvas2 = fig2.canvas.get_tk_widget()
254+
255+
plt.show(block=False)
256+
257+
assert_focus(tkcanvas2, expected_focus_state=True)
258+
259+
plt.close(fig2)
245260

246261

247262
@_isolated_tk_test(success_count=2)

0 commit comments

Comments
 (0)