Skip to content
This repository

Issue835 2: replacement for #835 #1192

Merged
merged 2 commits into from over 1 year ago

5 participants

Eric Firing Don't Add Me To Your Organization a.k.a The Travis Bot Phil Elson Michael Droettboom Benjamin Root
Eric Firing
Owner

As far as I can see, the monkey patching was not necessary at all, so I removed it. I think the result is much cleaner, and satisfies all requirements, to the extent that I have understood them. Testing on all backends is needed; I can do more of that tomorrow. macosx, tkagg, and qt4agg are tested. Testing on ipython notebook would be good, also.

Don't Add Me To Your Organization a.k.a The Travis Bot

This pull request fails (merged b76166f1 into 92721ed).

Phil Elson
Collaborator

Excuse the stupid question, but I cannot see where the interactive backends are overriding the backend_base manager's show method. I must be missing something very obvious...

Other than that, looks good to me.

Eric Firing
Owner

@pelson, it turned out that the GUI backend FigureManager classes already had show methods, so I didn't need to add anything.

Phil Elson
Collaborator

Looks good. I would like to get sign-off from @mdboom and @WeatherGod, but I think this is a really favourable approach.

Benjamin Root WeatherGod commented on the diff September 04, 2012
lib/matplotlib/backends/backend_macosx.py
... ...
@@ -375,9 +375,6 @@ def notify_axes_change(fig):
375 375
             if self.toolbar != None: self.toolbar.update()
376 376
         self.canvas.figure.add_axobserver(notify_axes_change)
377 377
 
378  
-        # This is ugly, but this is what tkagg and gtk are doing.
379  
-        # It is needed to get ginput() working.
380  
-        self.canvas.figure.show = lambda *args: self.show()
2
Benjamin Root Collaborator

Note a subtle difference between the macosx backend and most others for the show. macosx backend uses self.show() instead of self.window.show(). I am also concerned about the note saying that this is needed to make ginput() work correctly.

Eric Firing Owner

@WeatherGod: No problem, as far as I can see. The backends that were using self.window.show also had methods self.show that were defined as self.window.show, so the difference between patching in self.window.show and self.show was zilch.

Ginput works fine on macosx after this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Eric Firing
Owner

Rebased.

Don't Add Me To Your Organization a.k.a The Travis Bot

This pull request fails (merged 51ffd4b into 0f9f85f).

Phil Elson
Collaborator

@mdboom : Happy to merge?

Michael Droettboom
Owner

Yep. Merging now.

Michael Droettboom mdboom merged commit 15fd0ae into from September 05, 2012
Michael Droettboom mdboom closed this September 05, 2012
Eric Firing efiring deleted the branch May 28, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 2 unique commits by 2 authors.

Sep 04, 2012
Michael Droettboom Add a "show" method to figures that don't have a GUI backend. Fixed #835
.
faafa59
Eric Firing Remove figure.show monkeypatch from GUI backends.
This also adds the warn kwarg to figure.show for non-gui
backends.
51ffd4b
This page is out of date. Refresh to see the latest.
11  lib/matplotlib/backend_bases.py
@@ -2403,6 +2403,8 @@ def key_press_handler(event, canvas, toolbar=None):
2403 2403
                 else:
2404 2404
                     a.set_navigate(i==n)
2405 2405
 
  2406
+class NonGuiException(Exception):
  2407
+    pass
2406 2408
 
2407 2409
 class FigureManagerBase:
2408 2410
     """
@@ -2433,6 +2435,15 @@ def __init__(self, canvas, num):
2433 2435
 
2434 2436
         """
2435 2437
 
  2438
+    def show(self):
  2439
+        """
  2440
+        For GUI backends, show the figure window and redraw.
  2441
+        For non-GUI backends, raise an exception to be caught
  2442
+        by :meth:`~matplotlib.figure.Figure.show`, for an
  2443
+        optional warning.
  2444
+        """
  2445
+        raise NonGuiException()
  2446
+
2436 2447
     def destroy(self):
2437 2448
         pass
2438 2449
 
2  lib/matplotlib/backends/backend_fltkagg.py
@@ -143,7 +143,7 @@ def handle(self, event):
143 143
                     self._key=special_key[ikey]
144 144
                 except:
145 145
                     self._key=None
146  
-            
  146
+
147 147
             # TODO: Handle ctrl, alt, super modifiers.
148 148
             FigureCanvasBase.key_press_event(self._source, self._key)
149 149
             return 1
9  lib/matplotlib/backends/backend_gtk.py
@@ -335,14 +335,14 @@ def _get_key(self, event):
335 335
             key = chr(event.keyval)
336 336
         else:
337 337
             key = None
338  
-            
  338
+
339 339
         for key_mask, prefix in (
340 340
                                  [gdk.MOD4_MASK, 'super'],
341  
-                                 [gdk.MOD1_MASK, 'alt'], 
  341
+                                 [gdk.MOD1_MASK, 'alt'],
342 342
                                  [gdk.CONTROL_MASK, 'ctrl'],):
343 343
             if event.state & key_mask:
344 344
                 key = '{}+{}'.format(prefix, key)
345  
-        
  345
+
346 346
         return key
347 347
 
348 348
     def configure_event(self, widget, event):
@@ -553,9 +553,6 @@ def __init__(self, canvas, num):
553 553
 
554 554
         self.canvas.show()
555 555
 
556  
-        # attach a show method to the figure  for pylab ease of use
557  
-        self.canvas.figure.show = lambda *args: self.window.show()
558  
-
559 556
         self.vbox.pack_start(self.canvas, True, True)
560 557
 
561 558
         self.toolbar = self._get_toolbar(canvas)
5  lib/matplotlib/backends/backend_gtk3.py
@@ -378,9 +378,6 @@ def __init__(self, canvas, num):
378 378
 
379 379
         self.canvas.show()
380 380
 
381  
-        # attach a show method to the figure  for pylab ease of use
382  
-        self.canvas.figure.show = lambda *args: self.window.show()
383  
-
384 381
         self.vbox.pack_start(self.canvas, True, True, 0)
385 382
 
386 383
         self.toolbar = self._get_toolbar(canvas)
@@ -564,7 +561,7 @@ def configure_subplots(self, button):
564 561
 
565 562
 
566 563
         window = Gtk.Window()
567  
-        try: 
  564
+        try:
568 565
             window.set_icon_from_file(window_icon)
569 566
         except (SystemExit, KeyboardInterrupt):
570 567
             # re-raise exit type Exceptions
3  lib/matplotlib/backends/backend_macosx.py
@@ -376,9 +376,6 @@ def notify_axes_change(fig):
376 376
             if self.toolbar != None: self.toolbar.update()
377 377
         self.canvas.figure.add_axobserver(notify_axes_change)
378 378
 
379  
-        # This is ugly, but this is what tkagg and gtk are doing.
380  
-        # It is needed to get ginput() working.
381  
-        self.canvas.figure.show = lambda *args: self.show()
382 379
         if matplotlib.is_interactive():
383 380
             self.show()
384 381
 
5  lib/matplotlib/backends/backend_qt.py
@@ -260,9 +260,6 @@ def __init__( self, canvas, num ):
260 260
         if matplotlib.is_interactive():
261 261
             self.window.show()
262 262
 
263  
-        # attach a show method to the figure for pylab ease of use
264  
-        self.canvas.figure.show = lambda *args: self.window.show()
265  
-
266 263
         def notify_axes_change( fig ):
267 264
            # This will be called whenever the current axes is changed
268 265
            if self.toolbar != None: self.toolbar.update()
@@ -330,7 +327,7 @@ def _init_toolbar( self ):
330 327
                 continue
331 328
 
332 329
             fname = os.path.join(basedir, image_file + '.ppm')
333  
-            image = qt.QPixmap() 
  330
+            image = qt.QPixmap()
334 331
             image.load( fname )
335 332
 
336 333
             button = qt.QPushButton( qt.QIconSet( image ), "", self )
3  lib/matplotlib/backends/backend_qt4.py
@@ -435,9 +435,6 @@ def __init__( self, canvas, num ):
435 435
         if matplotlib.is_interactive():
436 436
             self.window.show()
437 437
 
438  
-        # attach a show method to the figure for pylab ease of use
439  
-        self.canvas.figure.show = lambda *args: self.window.show()
440  
-
441 438
         def notify_axes_change( fig ):
442 439
             # This will be called whenever the current axes is changed
443 440
             if self.toolbar is not None:
43  lib/matplotlib/backends/backend_tkagg.py
@@ -85,7 +85,7 @@ def new_figure_manager_given_figure(num, figure):
85 85
     """
86 86
     _focus = windowing.FocusManager()
87 87
     window = Tk.Tk()
88  
- 
  88
+
89 89
     if Tk.TkVersion >= 8.5:
90 90
         # put a mpl icon on the window rather than the default tk icon. Tkinter
91 91
         # doesn't allow colour icons on linux systems, but tk >=8.5 has a iconphoto
@@ -101,7 +101,7 @@ def new_figure_manager_given_figure(num, figure):
101 101
         except:
102 102
             # log the failure, but carry on
103 103
             verbose.report('Could not load matplotlib icon: %s' % sys.exc_info()[1])
104  
-            
  104
+
105 105
     canvas = FigureCanvasTkAgg(figure, master=window)
106 106
     figManager = FigureManagerTkAgg(canvas, num, window)
107 107
     if matplotlib.is_interactive():
@@ -199,7 +199,7 @@ class FigureCanvasTkAgg(FigureCanvasAgg):
199 199
                65439 : 'dec',
200 200
                65421 : 'enter',
201 201
                }
202  
-    
  202
+
203 203
     _keycode_lookup = {
204 204
                        262145: 'control',
205 205
                        524320: 'alt',
@@ -254,7 +254,7 @@ def filter_destroy(evt):
254 254
 
255 255
         self._master = master
256 256
         self._tkcanvas.focus_set()
257  
-                    
  257
+
258 258
     def resize(self, event):
259 259
         width, height = event.width, event.height
260 260
         if self._resize_callback is not None:
@@ -443,31 +443,31 @@ def _get_key(self, event):
443 443
             key = chr(val)
444 444
         else:
445 445
             key = None
446  
-            
447  
-        # add modifier keys to the key string. Bit details originate from 
  446
+
  447
+        # add modifier keys to the key string. Bit details originate from
448 448
         # http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
449  
-        # BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004; 
450  
-        # BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080; 
  449
+        # BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004;
  450
+        # BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080;
451 451
         # BIT_MB_1 = 0x100; BIT_MB_2 = 0x200; BIT_MB_3 = 0x400;
452  
-        # In general, the modifier key is excluded from the modifier flag, 
453  
-        # however this is not the case on "darwin", so double check that 
  452
+        # In general, the modifier key is excluded from the modifier flag,
  453
+        # however this is not the case on "darwin", so double check that
454 454
         # we aren't adding repeat modifier flags to a modifier key.
455  
-        modifiers = [(6, 'super', 'super'), 
456  
-                     (3, 'alt', 'alt'), 
  455
+        modifiers = [(6, 'super', 'super'),
  456
+                     (3, 'alt', 'alt'),
457 457
                      (2, 'ctrl', 'control'),
458 458
                     ]
459 459
         if sys.platform == 'darwin':
460  
-            modifiers = [(3, 'super', 'super'), 
461  
-                         (4, 'alt', 'alt'), 
  460
+            modifiers = [(3, 'super', 'super'),
  461
+                         (4, 'alt', 'alt'),
462 462
                          (2, 'ctrl', 'control'),
463 463
                         ]
464  
-        
  464
+
465 465
         if key is not None:
466 466
             # note, shift is not added to the keys as this is already accounted for
467 467
             for bitmask, prefix, key_name in modifiers:
468  
-                if event.state & (1 << bitmask) and key_name not in key: 
  468
+                if event.state & (1 << bitmask) and key_name not in key:
469 469
                     key = '{}+{}'.format(prefix, key)
470  
-                     
  470
+
471 471
         return key
472 472
 
473 473
     def key_press(self, event):
@@ -542,9 +542,6 @@ def notify_axes_change(fig):
542 542
             if self.toolbar != None: self.toolbar.update()
543 543
         self.canvas.figure.add_axobserver(notify_axes_change)
544 544
 
545  
-        # attach a show method to the figure for pylab ease of use
546  
-        self.canvas.figure.show = lambda *args: self.show()
547  
-
548 545
     def resize(self, width, height=None):
549 546
         # before 09-12-22, the resize method takes a single *event*
550 547
         # parameter. On the other hand, the resize method of other
@@ -852,14 +849,14 @@ def _init_toolbar(self):
852 849
 
853 850
         for text, tooltip_text, image_file, callback in self.toolitems:
854 851
             if text is None:
855  
-                # spacer, unhandled in Tk 
  852
+                # spacer, unhandled in Tk
856 853
                 pass
857 854
             else:
858 855
                 button = self._Button(text=text, file=image_file,
859 856
                                    command=getattr(self, callback))
860 857
                 if tooltip_text is not None:
861 858
                     ToolTip.createToolTip(button, tooltip_text)
862  
-        
  859
+
863 860
         self.message = Tk.StringVar(master=self)
864 861
         self._message_label = Tk.Label(master=self, textvariable=self.message)
865 862
         self._message_label.pack(side=Tk.RIGHT)
@@ -954,7 +951,7 @@ def leave(event):
954 951
             toolTip.hidetip()
955 952
         widget.bind('<Enter>', enter)
956 953
         widget.bind('<Leave>', leave)
957  
-        
  954
+
958 955
     def __init__(self, widget):
959 956
         self.widget = widget
960 957
         self.tipwindow = None
18  lib/matplotlib/backends/backend_wx.py
@@ -778,8 +778,8 @@ def Copy_to_Clipboard(self, event=None):
778 778
         "copy bitmap of canvas to system clipboard"
779 779
         bmp_obj = wx.BitmapDataObject()
780 780
         bmp_obj.SetBitmap(self.bitmap)
781  
-        
782  
-        if not wx.TheClipboard.IsOpened(): 
  781
+
  782
+        if not wx.TheClipboard.IsOpened():
783 783
            open_success = wx.TheClipboard.Open()
784 784
            if open_success:
785 785
               wx.TheClipboard.SetData(bmp_obj)
@@ -1251,7 +1251,7 @@ def _get_key(self, evt):
1251 1251
             key = None
1252 1252
 
1253 1253
         for meth, prefix in (
1254  
-                             [evt.AltDown, 'alt'], 
  1254
+                             [evt.AltDown, 'alt'],
1255 1255
                              [evt.ControlDown, 'ctrl'], ):
1256 1256
             if meth():
1257 1257
                 key = '{}+{}'.format(prefix, key)
@@ -1421,7 +1421,7 @@ def _create_wx_app():
1421 1421
         # retain a reference to the app object so it does not get garbage
1422 1422
         # collected and cause segmentation faults
1423 1423
         _create_wx_app.theWxApp = wxapp
1424  
-        
  1424
+
1425 1425
 
1426 1426
 def draw_if_interactive():
1427 1427
     """
@@ -1521,7 +1521,7 @@ def __init__(self, num, fig):
1521 1521
         self.Fit()
1522 1522
 
1523 1523
         self.canvas.SetMinSize((2, 2))
1524  
-        
  1524
+
1525 1525
         # give the window a matplotlib icon rather than the stock one.
1526 1526
         # This is not currently working on Linux and is untested elsewhere.
1527 1527
         #icon_path = os.path.join(matplotlib.rcParams['datapath'],
@@ -1603,12 +1603,6 @@ def notify_axes_change(fig):
1603 1603
             if self.tb != None: self.tb.update()
1604 1604
         self.canvas.figure.add_axobserver(notify_axes_change)
1605 1605
 
1606  
-        def showfig(*args):
1607  
-            frame.Show()
1608  
-
1609  
-        # attach a show method to the figure
1610  
-        self.canvas.figure.show = showfig
1611  
-
1612 1606
     def show(self):
1613 1607
         self.frame.Show()
1614 1608
 
@@ -1882,7 +1876,7 @@ def save_figure(self, *args):
1882 1876
                     os.path.join(dirname, filename), format=format)
1883 1877
             except Exception as e:
1884 1878
                 error_msg_wx(str(e))
1885  
-    
  1879
+
1886 1880
     def set_cursor(self, cursor):
1887 1881
         cursor =wx.StockCursor(cursord[cursor])
1888 1882
         self.canvas.SetCursor( cursor )
26  lib/matplotlib/figure.py
@@ -42,7 +42,7 @@
42 42
 from matplotlib.text import Text, _process_text_args
43 43
 from matplotlib.transforms import (Affine2D, Bbox, BboxTransformTo,
44 44
                                     TransformedBbox)
45  
-
  45
+from matplotlib.backend_bases import NonGuiException
46 46
 
47 47
 docstring.interpd.update(projection_names = get_projection_names())
48 48
 
@@ -338,6 +338,26 @@ def _setup_canvas(self):
338 338
         backend_mod = mbackends.pylab_setup()[0]
339 339
         return backend_mod.FigureCanvas(self)
340 340
 
  341
+    def show(self, warn=True):
  342
+        """
  343
+        If using a GUI backend, display the figure window.
  344
+
  345
+        For non-GUI backends, this does nothing, in which case
  346
+        a warning will be issued if *warn* is True.
  347
+        """
  348
+        manager = getattr(self.canvas, 'manager')
  349
+        if manager is not None:
  350
+            try:
  351
+                manager.show()
  352
+                return
  353
+            except NonGuiException:
  354
+                pass
  355
+        if warn:
  356
+            import warnings
  357
+            warnings.warn(
  358
+                "matplotlib is currently using a non-GUI backend, "
  359
+                "so cannot show the figure")
  360
+
341 361
     def _get_axes(self):
342 362
         return self._axstack.as_list()
343 363
 
@@ -1188,10 +1208,10 @@ def __getstate__(self):
1188 1208
         # and re-attached to another.
1189 1209
         for attr_to_pop in ('_axobservers', 'show', 'canvas', '_cachedRenderer') :
1190 1210
             state.pop(attr_to_pop, None)
1191  
-        
  1211
+
1192 1212
         # add version information to the state
1193 1213
         state['__mpl_version__'] = _mpl_version
1194  
-        
  1214
+
1195 1215
         # check to see if the figure has a manager and whether it is registered
1196 1216
         # with pyplot
1197 1217
         if getattr(self.canvas, 'manager', None) is not None:
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.