Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d6ae8a5

Browse files
authored
Merge pull request #11179 from Zac-HD/focus-manager
Convert internal tk focus helper to a context manager
2 parents bcaa204 + c0df144 commit d6ae8a5

2 files changed

Lines changed: 60 additions & 41 deletions

File tree

lib/matplotlib/backends/_backend_tk.py

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66
import sys
77
import tkinter as Tk
88
from tkinter.simpledialog import SimpleDialog
9+
from contextlib import contextmanager
910

1011
import numpy as np
1112

1213
from . import _tkagg
13-
from matplotlib.backends.backend_agg import FigureCanvasAgg
14-
import matplotlib.backends.windowing as windowing
1514

1615
import matplotlib
1716
from matplotlib import backend_tools, rcParams
@@ -23,6 +22,22 @@
2322
from matplotlib.figure import Figure
2423
from matplotlib.widgets import SubplotTool
2524

25+
try:
26+
from matplotlib._windowing import GetForegroundWindow, SetForegroundWindow
27+
except ImportError:
28+
@contextmanager
29+
def _restore_foreground_window_at_end():
30+
yield
31+
else:
32+
@contextmanager
33+
def _restore_foreground_window_at_end():
34+
foreground = GetForegroundWindow()
35+
try:
36+
yield
37+
finally:
38+
if rcParams['tk.window_focus']:
39+
SetForegroundWindow(foreground)
40+
2641

2742
_log = logging.getLogger(__name__)
2843

@@ -540,19 +555,19 @@ def show(self):
540555
this function doesn't segfault but causes the
541556
PyEval_RestoreThread: NULL state bug on win32
542557
"""
543-
_focus = windowing.FocusManager()
544-
if not self._shown:
545-
def destroy(*args):
546-
self.window = None
547-
Gcf.destroy(self._num)
548-
self.canvas._tkcanvas.bind("<Destroy>", destroy)
549-
self.window.deiconify()
550-
else:
551-
self.canvas.draw_idle()
552-
# Raise the new window.
553-
self.canvas.manager.window.attributes('-topmost', 1)
554-
self.canvas.manager.window.attributes('-topmost', 0)
555-
self._shown = True
558+
with _restore_foreground_window_at_end():
559+
if not self._shown:
560+
def destroy(*args):
561+
self.window = None
562+
Gcf.destroy(self._num)
563+
self.canvas._tkcanvas.bind("<Destroy>", destroy)
564+
self.window.deiconify()
565+
else:
566+
self.canvas.draw_idle()
567+
# Raise the new window.
568+
self.canvas.manager.window.attributes('-topmost', 1)
569+
self.canvas.manager.window.attributes('-topmost', 0)
570+
self._shown = True
556571

557572
def destroy(self, *args):
558573
if self.window is not None:
@@ -716,9 +731,9 @@ def set_active(self, ind):
716731
self._active = [self._axes[i] for i in self._ind]
717732

718733
def update(self):
719-
_focus = windowing.FocusManager()
720734
self._axes = self.canvas.figure.axes
721-
NavigationToolbar2.update(self)
735+
with _restore_foreground_window_at_end():
736+
NavigationToolbar2.update(self)
722737

723738

724739
class ToolTip(object):
@@ -989,29 +1004,29 @@ def new_figure_manager_given_figure(cls, num, figure):
9891004
"""
9901005
Create a new figure manager instance for the given figure.
9911006
"""
992-
_focus = windowing.FocusManager()
993-
window = Tk.Tk(className="matplotlib")
994-
window.withdraw()
995-
996-
# Put a mpl icon on the window rather than the default tk icon.
997-
# Tkinter doesn't allow colour icons on linux systems, but tk>=8.5 has
998-
# a iconphoto command which we call directly. Source:
999-
# http://mail.python.org/pipermail/tkinter-discuss/2006-November/000954.html
1000-
icon_fname = os.path.join(
1001-
rcParams['datapath'], 'images', 'matplotlib.ppm')
1002-
icon_img = Tk.PhotoImage(file=icon_fname)
1003-
try:
1004-
window.tk.call('wm', 'iconphoto', window._w, icon_img)
1005-
except Exception as exc:
1006-
# log the failure (due e.g. to Tk version), but carry on
1007-
_log.info('Could not load matplotlib icon: %s', exc)
1008-
1009-
canvas = cls.FigureCanvas(figure, master=window)
1010-
manager = cls.FigureManager(canvas, num, window)
1011-
if matplotlib.is_interactive():
1012-
manager.show()
1013-
canvas.draw_idle()
1014-
return manager
1007+
with _restore_foreground_window_at_end():
1008+
window = Tk.Tk(className="matplotlib")
1009+
window.withdraw()
1010+
1011+
# Put a mpl icon on the window rather than the default tk icon.
1012+
# Tkinter doesn't allow colour icons on linux systems, but tk>=8.5 has
1013+
# a iconphoto command which we call directly. Source:
1014+
# http://mail.python.org/pipermail/tkinter-discuss/2006-November/000954.html
1015+
icon_fname = os.path.join(
1016+
rcParams['datapath'], 'images', 'matplotlib.ppm')
1017+
icon_img = Tk.PhotoImage(file=icon_fname)
1018+
try:
1019+
window.tk.call('wm', 'iconphoto', window._w, icon_img)
1020+
except Exception as exc:
1021+
# log the failure (due e.g. to Tk version), but carry on
1022+
_log.info('Could not load matplotlib icon: %s', exc)
1023+
1024+
canvas = cls.FigureCanvas(figure, master=window)
1025+
manager = cls.FigureManager(canvas, num, window)
1026+
if matplotlib.is_interactive():
1027+
manager.show()
1028+
canvas.draw_idle()
1029+
return manager
10151030

10161031
@staticmethod
10171032
def trigger_manager_draw(manager):

lib/matplotlib/backends/windowing.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
effectively disabled.
66
77
It uses a tiny C++ extension module to access MS Win functions.
8+
9+
This module is deprecated and will be removed in version 3.2
810
"""
911

10-
from matplotlib import rcParams
12+
from matplotlib import rcParams, cbook
13+
14+
cbook.warn_deprecated('3.0', obj_type='module', name='backends.windowing')
1115

1216
try:
1317
if not rcParams['tk.window_focus']:

0 commit comments

Comments
 (0)