Skip to content

Commit 2505c81

Browse files
committed
ENH: make tkagg blocking work
The issue is that we need a tk window to grab the mainloop. In the upstream tkagg backend we get a manager from Gcf, but in mpl-gui we are not populating Gcf so we need to patch the tkagg backend. To get the run-time patching to work as we also needed to add a path to directly use the Backend classes in the modules rather than re-constituting another class!
1 parent de51fa2 commit 2505c81

File tree

4 files changed

+38
-4
lines changed

4 files changed

+38
-4
lines changed

mpl_gui/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from itertools import count
1818

1919
from matplotlib.backend_bases import FigureCanvasBase as _FigureCanvasBase
20+
from matplotlib.cbook import _setattr_cm
2021

2122
from ._figure import Figure # noqa: F401
2223

@@ -78,7 +79,8 @@ def show(figs, *, block=None, timeout=0):
7879

7980
if block and len(managers):
8081
if timeout == 0:
81-
backend.Show().mainloop()
82+
with _setattr_cm(backend, get_active_managers=lambda: managers):
83+
backend.mainloop()
8284
elif len(managers):
8385
manager, *_ = managers
8486
manager.canvas.start_event_loop(timeout=timeout)

mpl_gui/_manage_backend.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,17 @@ def select_gui_toolkit(newbackend=None):
8989
# creating a "class" that inherits from backend_bases._Backend and whose
9090
# body is filled with the module's globals.
9191

92-
backend_name = cbook._backend_module_name(newbackend)
92+
if newbackend.lower() == 'tkagg':
93+
backend_name = f'mpl_gui._patched_backends.{newbackend.lower()}'
94+
else:
95+
backend_name = cbook._backend_module_name(newbackend)
9396

94-
class backend_mod(matplotlib.backend_bases._Backend):
95-
locals().update(vars(importlib.import_module(backend_name)))
97+
mod = importlib.import_module(backend_name)
98+
if hasattr(mod, 'Backend'):
99+
backend_mod = mod.Backend
100+
else:
101+
class backend_mod(matplotlib.backend_bases._Backend):
102+
locals().update(vars())
96103

97104
rc_params_string = newbackend
98105

mpl_gui/_patched_backends/__init__.py

Whitespace-only changes.

mpl_gui/_patched_backends/tkagg.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from matplotlib.backends.backend_tkagg import _BackendTkAgg
2+
3+
4+
@_BackendTkAgg.export
5+
class _PatchedBackendTkAgg(_BackendTkAgg):
6+
@staticmethod
7+
def get_active_managers():
8+
raise RuntimeError("This method should never actually be called")
9+
10+
@classmethod
11+
def mainloop(cls):
12+
managers = cls.get_active_managers()
13+
if managers:
14+
first_manager = managers[0]
15+
manager_class = type(first_manager)
16+
if manager_class._owns_mainloop:
17+
return
18+
manager_class._owns_mainloop = True
19+
try:
20+
first_manager.window.mainloop()
21+
finally:
22+
manager_class._owns_mainloop = False
23+
24+
25+
Backend = _PatchedBackendTkAgg

0 commit comments

Comments
 (0)