Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcd185ab

Browse files
authored
Merge pull request#23101 from anntzer/inheritable-backend-show
Move show() to somewhere naturally inheritable / document what pyplot expects from a backend.
2 parents19d9340 +86f26a0 commitcd185ab

File tree

11 files changed

+174
-90
lines changed

11 files changed

+174
-90
lines changed

‎lib/matplotlib/backend_bases.py

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2848,6 +2848,53 @@ def create_with_canvas(cls, canvas_class, figure, num):
28482848
"""
28492849
returncls(canvas_class(figure),num)
28502850

2851+
@classmethod
2852+
defstart_main_loop(cls):
2853+
"""
2854+
Start the main event loop.
2855+
2856+
This method is called by `.FigureManagerBase.pyplot_show`, which is the
2857+
implementation of `.pyplot.show`. To customize the behavior of
2858+
`.pyplot.show`, interactive backends should usually override
2859+
`~.FigureManagerBase.start_main_loop`; if more customized logic is
2860+
necessary, `~.FigureManagerBase.pyplot_show` can also be overridden.
2861+
"""
2862+
2863+
@classmethod
2864+
defpyplot_show(cls,*,block=None):
2865+
"""
2866+
Show all figures. This method is the implementation of `.pyplot.show`.
2867+
2868+
To customize the behavior of `.pyplot.show`, interactive backends
2869+
should usually override `~.FigureManagerBase.start_main_loop`; if more
2870+
customized logic is necessary, `~.FigureManagerBase.pyplot_show` can
2871+
also be overridden.
2872+
2873+
Parameters
2874+
----------
2875+
block : bool, optional
2876+
Whether to block by calling ``start_main_loop``. The default,
2877+
None, means to block if we are neither in IPython's ``%pylab`` mode
2878+
nor in ``interactive`` mode.
2879+
"""
2880+
managers=Gcf.get_all_fig_managers()
2881+
ifnotmanagers:
2882+
return
2883+
formanagerinmanagers:
2884+
try:
2885+
manager.show()# Emits a warning for non-interactive backend.
2886+
exceptNonGuiExceptionasexc:
2887+
_api.warn_external(str(exc))
2888+
ifblockisNone:
2889+
# Hack: Are we in IPython's %pylab mode? In pylab mode, IPython
2890+
# (>= 0.10) tacks a _needmain attribute onto pyplot.show (always
2891+
# set to False).
2892+
ipython_pylab=hasattr(
2893+
getattr(sys.modules.get("pyplot"),"show",None),"_needmain")
2894+
block=notipython_pylabandnotis_interactive()
2895+
ifblock:
2896+
cls.start_main_loop()
2897+
28512898
defshow(self):
28522899
"""
28532900
For GUI backends, show the figure window and redraw.
@@ -3526,7 +3573,12 @@ def new_figure_manager_given_figure(cls, num, figure):
35263573

35273574
@classmethod
35283575
defdraw_if_interactive(cls):
3529-
ifcls.mainloopisnotNoneandis_interactive():
3576+
manager_class=cls.FigureCanvas.manager_class
3577+
# Interactive backends reimplement start_main_loop or pyplot_show.
3578+
backend_is_interactive= (
3579+
manager_class.start_main_loop!=FigureManagerBase.start_main_loop
3580+
ormanager_class.pyplot_show!=FigureManagerBase.pyplot_show)
3581+
ifbackend_is_interactiveandis_interactive():
35303582
manager=Gcf.get_active()
35313583
ifmanager:
35323584
manager.canvas.draw_idle()
@@ -3554,8 +3606,8 @@ def show(cls, *, block=None):
35543606
# Hack: Are we in IPython's %pylab mode? In pylab mode, IPython
35553607
# (>= 0.10) tacks a _needmain attribute onto pyplot.show (always
35563608
# set to False).
3557-
frommatplotlibimportpyplot
3558-
ipython_pylab=hasattr(pyplot.show,"_needmain")
3609+
ipython_pylab=hasattr(
3610+
getattr(sys.modules.get("pyplot"),"show",None),"_needmain")
35593611
block=notipython_pylabandnotis_interactive()
35603612
ifblock:
35613613
cls.mainloop()

‎lib/matplotlib/backends/_backend_gtk.py

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
frommatplotlibimport_api,backend_tools,cbook
1010
frommatplotlib._pylab_helpersimportGcf
1111
frommatplotlib.backend_basesimport (
12-
_Backend,FigureManagerBase,NavigationToolbar2,TimerBase)
12+
_Backend,FigureCanvasBase,FigureManagerBase,NavigationToolbar2,
13+
TimerBase)
1314
frommatplotlib.backend_toolsimportCursors
1415

1516
importgi
@@ -113,6 +114,10 @@ def _on_timer(self):
113114
returnFalse
114115

115116

117+
class_FigureCanvasGTK(FigureCanvasBase):
118+
_timer_cls=TimerGTK
119+
120+
116121
class_FigureManagerGTK(FigureManagerBase):
117122
"""
118123
Attributes
@@ -192,6 +197,25 @@ def destroy(self, *args):
192197
self.window.destroy()
193198
self.canvas.destroy()
194199

200+
@classmethod
201+
defstart_main_loop(cls):
202+
global_application
203+
if_applicationisNone:
204+
return
205+
206+
try:
207+
_application.run()# Quits when all added windows close.
208+
exceptKeyboardInterrupt:
209+
# Ensure all windows can process their close event from
210+
# _shutdown_application.
211+
context=GLib.MainContext.default()
212+
whilecontext.pending():
213+
context.iteration(True)
214+
raise
215+
finally:
216+
# Running after quit is undefined, so create a new one next time.
217+
_application=None
218+
195219
defshow(self):
196220
# show the figure window
197221
self.window.show()
@@ -305,22 +329,4 @@ class _BackendGTK(_Backend):
305329
Gtk.get_minor_version(),
306330
Gtk.get_micro_version(),
307331
)
308-
309-
@staticmethod
310-
defmainloop():
311-
global_application
312-
if_applicationisNone:
313-
return
314-
315-
try:
316-
_application.run()# Quits when all added windows close.
317-
exceptKeyboardInterrupt:
318-
# Ensure all windows can process their close event from
319-
# _shutdown_application.
320-
context=GLib.MainContext.default()
321-
whilecontext.pending():
322-
context.iteration(True)
323-
raise
324-
finally:
325-
# Running after quit is undefined, so create a new one next time.
326-
_application=None
332+
mainloop=_FigureManagerGTK.start_main_loop

‎lib/matplotlib/backends/_backend_tk.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,20 @@ def create_with_canvas(cls, canvas_class, figure, num):
484484
canvas.draw_idle()
485485
returnmanager
486486

487+
@classmethod
488+
defstart_main_loop(cls):
489+
managers=Gcf.get_all_fig_managers()
490+
ifmanagers:
491+
first_manager=managers[0]
492+
manager_class=type(first_manager)
493+
ifmanager_class._owns_mainloop:
494+
return
495+
manager_class._owns_mainloop=True
496+
try:
497+
first_manager.window.mainloop()
498+
finally:
499+
manager_class._owns_mainloop=False
500+
487501
def_update_window_dpi(self,*args):
488502
newdpi=self._window_dpi.get()
489503
self.window.call('tk','scaling',newdpi/72)
@@ -1018,18 +1032,6 @@ def trigger(self, *args):
10181032
@_Backend.export
10191033
class_BackendTk(_Backend):
10201034
backend_version=tk.TkVersion
1035+
FigureCanvas=FigureCanvasTk
10211036
FigureManager=FigureManagerTk
1022-
1023-
@staticmethod
1024-
defmainloop():
1025-
managers=Gcf.get_all_fig_managers()
1026-
ifmanagers:
1027-
first_manager=managers[0]
1028-
manager_class=type(first_manager)
1029-
ifmanager_class._owns_mainloop:
1030-
return
1031-
manager_class._owns_mainloop=True
1032-
try:
1033-
first_manager.window.mainloop()
1034-
finally:
1035-
manager_class._owns_mainloop=False
1037+
mainloop=FigureManagerTk.start_main_loop

‎lib/matplotlib/backends/backend_gtk3.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
importmatplotlibasmpl
88
frommatplotlibimport_api,backend_tools,cbook
99
frommatplotlib.backend_basesimport (
10-
FigureCanvasBase,ToolContainerBase,
11-
CloseEvent,KeyEvent,LocationEvent,MouseEvent,ResizeEvent)
10+
ToolContainerBase,CloseEvent,KeyEvent,LocationEvent,MouseEvent,
11+
ResizeEvent)
1212

1313
try:
1414
importgi
@@ -26,8 +26,8 @@
2626

2727
fromgi.repositoryimportGio,GLib,GObject,Gtk,Gdk
2828
from .import_backend_gtk
29-
from ._backend_gtkimport (
30-
_BackendGTK,_FigureManagerGTK,_NavigationToolbar2GTK,
29+
from ._backend_gtkimport (# noqa: F401 # pylint: disable=W0611
30+
_BackendGTK,_FigureCanvasGTK,_FigureManagerGTK,_NavigationToolbar2GTK,
3131
TimerGTKasTimerGTK3,
3232
)
3333

@@ -52,9 +52,8 @@ def _mpl_to_gtk_cursor(mpl_cursor):
5252
_backend_gtk.mpl_to_gtk_cursor_name(mpl_cursor))
5353

5454

55-
classFigureCanvasGTK3(FigureCanvasBase,Gtk.DrawingArea):
55+
classFigureCanvasGTK3(_FigureCanvasGTK,Gtk.DrawingArea):
5656
required_interactive_framework="gtk3"
57-
_timer_cls=TimerGTK3
5857
manager_class=_api.classproperty(lambdacls:FigureManagerGTK3)
5958
# Setting this as a static constant prevents
6059
# this resulting expression from leaking

‎lib/matplotlib/backends/backend_gtk4.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
importmatplotlibasmpl
66
frommatplotlibimport_api,backend_tools,cbook
77
frommatplotlib.backend_basesimport (
8-
FigureCanvasBase,ToolContainerBase,
9-
KeyEvent,LocationEvent,MouseEvent,ResizeEvent)
8+
ToolContainerBase,KeyEvent,LocationEvent,MouseEvent,ResizeEvent)
109

1110
try:
1211
importgi
@@ -24,16 +23,15 @@
2423

2524
fromgi.repositoryimportGio,GLib,Gtk,Gdk,GdkPixbuf
2625
from .import_backend_gtk
27-
from ._backend_gtkimport (
28-
_BackendGTK,_FigureManagerGTK,_NavigationToolbar2GTK,
26+
from ._backend_gtkimport (# noqa: F401 # pylint: disable=W0611
27+
_BackendGTK,_FigureCanvasGTK,_FigureManagerGTK,_NavigationToolbar2GTK,
2928
TimerGTKasTimerGTK4,
3029
)
3130

3231

33-
classFigureCanvasGTK4(FigureCanvasBase,Gtk.DrawingArea):
32+
classFigureCanvasGTK4(_FigureCanvasGTK,Gtk.DrawingArea):
3433
required_interactive_framework="gtk4"
3534
supports_blit=False
36-
_timer_cls=TimerGTK4
3735
manager_class=_api.classproperty(lambdacls:FigureManagerGTK4)
3836
_context_is_scaled=False
3937

‎lib/matplotlib/backends/backend_macosx.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ def _close_button_pressed(self):
165165
defclose(self):
166166
returnself._close_button_pressed()
167167

168+
@classmethod
169+
defstart_main_loop(cls):
170+
_macosx.show()
171+
168172
defshow(self):
169173
ifnotself._shown:
170174
self._show()
@@ -177,7 +181,4 @@ def show(self):
177181
class_BackendMac(_Backend):
178182
FigureCanvas=FigureCanvasMac
179183
FigureManager=FigureManagerMac
180-
181-
@staticmethod
182-
defmainloop():
183-
_macosx.show()
184+
mainloop=FigureManagerMac.start_main_loop

‎lib/matplotlib/backends/backend_qt.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,13 @@ def resize(self, width, height):
583583
self.canvas.resize(width,height)
584584
self.window.resize(width+extra_width,height+extra_height)
585585

586+
@classmethod
587+
defstart_main_loop(cls):
588+
qapp=QtWidgets.QApplication.instance()
589+
ifqapp:
590+
with_maybe_allow_interrupt(qapp):
591+
qt_compat._exec(qapp)
592+
586593
defshow(self):
587594
self.window.show()
588595
ifmpl.rcParams['figure.raise_window']:
@@ -1007,9 +1014,4 @@ class _BackendQT(_Backend):
10071014
backend_version=__version__
10081015
FigureCanvas=FigureCanvasQT
10091016
FigureManager=FigureManagerQT
1010-
1011-
@staticmethod
1012-
defmainloop():
1013-
qapp=QtWidgets.QApplication.instance()
1014-
with_maybe_allow_interrupt(qapp):
1015-
qt_compat._exec(qapp)
1017+
mainloop=FigureManagerQT.start_main_loop

‎lib/matplotlib/backends/backend_webagg.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,24 @@ def run(self):
5353
classFigureManagerWebAgg(core.FigureManagerWebAgg):
5454
_toolbar2_class=core.NavigationToolbar2WebAgg
5555

56+
@classmethod
57+
defpyplot_show(cls,*,block=None):
58+
WebAggApplication.initialize()
59+
60+
url="http://{address}:{port}{prefix}".format(
61+
address=WebAggApplication.address,
62+
port=WebAggApplication.port,
63+
prefix=WebAggApplication.url_prefix)
64+
65+
ifmpl.rcParams['webagg.open_in_browser']:
66+
importwebbrowser
67+
ifnotwebbrowser.open(url):
68+
print("To view figure, visit {0}".format(url))
69+
else:
70+
print("To view figure, visit {0}".format(url))
71+
72+
WebAggApplication.start()
73+
5674

5775
classFigureCanvasWebAgg(core.FigureCanvasWebAggCore):
5876
manager_class=FigureManagerWebAgg
@@ -307,21 +325,3 @@ def ipython_inline_display(figure):
307325
class_BackendWebAgg(_Backend):
308326
FigureCanvas=FigureCanvasWebAgg
309327
FigureManager=FigureManagerWebAgg
310-
311-
@staticmethod
312-
defshow(*,block=None):
313-
WebAggApplication.initialize()
314-
315-
url="http://{address}:{port}{prefix}".format(
316-
address=WebAggApplication.address,
317-
port=WebAggApplication.port,
318-
prefix=WebAggApplication.url_prefix)
319-
320-
ifmpl.rcParams['webagg.open_in_browser']:
321-
importwebbrowser
322-
ifnotwebbrowser.open(url):
323-
print("To view figure, visit {0}".format(url))
324-
else:
325-
print("To view figure, visit {0}".format(url))
326-
327-
WebAggApplication.start()

‎lib/matplotlib/backends/backend_wx.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,13 @@ def create_with_canvas(cls, canvas_class, figure, num):
999999
figure.canvas.draw_idle()
10001000
returnmanager
10011001

1002+
@classmethod
1003+
defstart_main_loop(cls):
1004+
ifnotwx.App.IsMainLoopRunning():
1005+
wxapp=wx.GetApp()
1006+
ifwxappisnotNone:
1007+
wxapp.MainLoop()
1008+
10021009
defshow(self):
10031010
# docstring inherited
10041011
self.frame.Show()
@@ -1365,10 +1372,4 @@ def trigger(self, *args, **kwargs):
13651372
class_BackendWx(_Backend):
13661373
FigureCanvas=FigureCanvasWx
13671374
FigureManager=FigureManagerWx
1368-
1369-
@staticmethod
1370-
defmainloop():
1371-
ifnotwx.App.IsMainLoopRunning():
1372-
wxapp=wx.GetApp()
1373-
ifwxappisnotNone:
1374-
wxapp.MainLoop()
1375+
mainloop=FigureManagerWx.start_main_loop

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp