Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions doc/api/next_api_changes/behavior/30852-PR.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Default focus behavior of ``FigureCanvasTkAgg``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Previously, when a `.FigureCanvasTkAgg` object was created, focus was set to the
canvas by default. Now, focus is not set anymore. If focus is desired on the canvas,
it can be set explicitly after creation using the ``focus_set()`` method of Tkinter
widgets.

See :doc:`../../../gallery/user_interfaces/embedding_in_tk_sgskip` for an example of
focus-setting in an embedded Matplotlib figure in a Tkinter application.
3 changes: 3 additions & 0 deletions galleries/examples/user_interfaces/embedding_in_tk_sgskip.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,7 @@ def update_frequency(new_val):
toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=True)

# Explicitly set focus to canvas for it to receive key press events
canvas.get_tk_widget().focus_set()

tkinter.mainloop()
2 changes: 0 additions & 2 deletions lib/matplotlib/backends/_backend_tk.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,6 @@ def filter_destroy(event):
CloseEvent("close_event", self)._process()
filter_destroy_id = root.bind("<Destroy>", filter_destroy, "+")

self._tkcanvas.focus_set()

self._rubberband_rect_black = None
self._rubberband_rect_white = None

Expand Down
53 changes: 34 additions & 19 deletions lib/matplotlib/tests/test_backend_tk.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,33 +215,48 @@ def test_save_figure_return():
print("success")


@_isolated_tk_test(success_count=1)
@_isolated_tk_test(success_count=3)
def test_canvas_focus():
import matplotlib
import tkinter as tk
import matplotlib.pyplot as plt
success = []
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
matplotlib.use('Tkagg')

def check_focus():
tkcanvas = fig.canvas.get_tk_widget()
# Give the plot window time to appear
if not tkcanvas.winfo_viewable():
tkcanvas.wait_visibility()
# Make sure the canvas has the focus, so that it's able to receive
# keyboard events.
if tkcanvas.focus_lastfor() == tkcanvas:
success.append(True)
plt.close()
root.destroy()
def assert_focus(widget, expected_focus_state):
if not widget.winfo_viewable():
widget.wait_visibility()

has_focus = (widget.focus_get() == widget)

if has_focus == expected_focus_state:
print("success")

root = tk.Tk()
fig = plt.figure()
plt.plot([1, 2, 3])
root.after(0, plt.show)
root.after(100, check_focus)
root.mainloop()
canvas = FigureCanvasTkAgg(fig, root)
tkcanvas = canvas.get_tk_widget()
tkcanvas.pack()

if success:
print("success")
# Test 1: Default Behavior (No Focus Stealing)
assert_focus(tkcanvas, expected_focus_state=False)

# Test 2: Explicit Focus
tkcanvas.focus_force()
assert_focus(tkcanvas, expected_focus_state=True)

plt.close(fig)
root.destroy()

# Test 3: Showing the plot should grab focus
fig2 = plt.figure()
tkcanvas2 = fig2.canvas.get_tk_widget()

plt.show(block=False)

assert_focus(tkcanvas2, expected_focus_state=True)

plt.close(fig2)


@_isolated_tk_test(success_count=2)
Expand Down
Loading