Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Issue835 2: replacement for #835 #1192

Merged
merged 2 commits into from

5 participants

@efiring
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.

@travisbot

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

@pelson
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.

@efiring
Owner

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

@pelson
Collaborator

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

@WeatherGod WeatherGod commented on the diff
lib/matplotlib/backends/backend_macosx.py
@@ -375,9 +375,6 @@ def notify_axes_change(fig):
if self.toolbar != None: self.toolbar.update()
self.canvas.figure.add_axobserver(notify_axes_change)
- # This is ugly, but this is what tkagg and gtk are doing.
- # It is needed to get ginput() working.
- self.canvas.figure.show = lambda *args: self.show()
@WeatherGod 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.

@efiring Owner
efiring added a note

@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
@efiring
Owner

Rebased.

@travisbot

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

@pelson
Collaborator

@mdboom : Happy to merge?

@mdboom
Owner

Yep. Merging now.

@mdboom mdboom merged commit 15fd0ae into matplotlib:master
@efiring efiring deleted the efiring:issue835_2 branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 4, 2012
  1. @mdboom @efiring
  2. @efiring

    Remove figure.show monkeypatch from GUI backends.

    efiring authored
    This also adds the warn kwarg to figure.show for non-gui
    backends.
This page is out of date. Refresh to see the latest.
View
11 lib/matplotlib/backend_bases.py
@@ -2403,6 +2403,8 @@ def key_press_handler(event, canvas, toolbar=None):
else:
a.set_navigate(i==n)
+class NonGuiException(Exception):
+ pass
class FigureManagerBase:
"""
@@ -2433,6 +2435,15 @@ def __init__(self, canvas, num):
"""
+ def show(self):
+ """
+ For GUI backends, show the figure window and redraw.
+ For non-GUI backends, raise an exception to be caught
+ by :meth:`~matplotlib.figure.Figure.show`, for an
+ optional warning.
+ """
+ raise NonGuiException()
+
def destroy(self):
pass
View
2  lib/matplotlib/backends/backend_fltkagg.py
@@ -143,7 +143,7 @@ def handle(self, event):
self._key=special_key[ikey]
except:
self._key=None
-
+
# TODO: Handle ctrl, alt, super modifiers.
FigureCanvasBase.key_press_event(self._source, self._key)
return 1
View
9 lib/matplotlib/backends/backend_gtk.py
@@ -335,14 +335,14 @@ def _get_key(self, event):
key = chr(event.keyval)
else:
key = None
-
+
for key_mask, prefix in (
[gdk.MOD4_MASK, 'super'],
- [gdk.MOD1_MASK, 'alt'],
+ [gdk.MOD1_MASK, 'alt'],
[gdk.CONTROL_MASK, 'ctrl'],):
if event.state & key_mask:
key = '{}+{}'.format(prefix, key)
-
+
return key
def configure_event(self, widget, event):
@@ -553,9 +553,6 @@ def __init__(self, canvas, num):
self.canvas.show()
- # attach a show method to the figure for pylab ease of use
- self.canvas.figure.show = lambda *args: self.window.show()
-
self.vbox.pack_start(self.canvas, True, True)
self.toolbar = self._get_toolbar(canvas)
View
5 lib/matplotlib/backends/backend_gtk3.py
@@ -378,9 +378,6 @@ def __init__(self, canvas, num):
self.canvas.show()
- # attach a show method to the figure for pylab ease of use
- self.canvas.figure.show = lambda *args: self.window.show()
-
self.vbox.pack_start(self.canvas, True, True, 0)
self.toolbar = self._get_toolbar(canvas)
@@ -564,7 +561,7 @@ def configure_subplots(self, button):
window = Gtk.Window()
- try:
+ try:
window.set_icon_from_file(window_icon)
except (SystemExit, KeyboardInterrupt):
# re-raise exit type Exceptions
View
3  lib/matplotlib/backends/backend_macosx.py
@@ -376,9 +376,6 @@ def notify_axes_change(fig):
if self.toolbar != None: self.toolbar.update()
self.canvas.figure.add_axobserver(notify_axes_change)
- # This is ugly, but this is what tkagg and gtk are doing.
- # It is needed to get ginput() working.
- self.canvas.figure.show = lambda *args: self.show()
@WeatherGod 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.

@efiring Owner
efiring added a note

@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
if matplotlib.is_interactive():
self.show()
View
5 lib/matplotlib/backends/backend_qt.py
@@ -260,9 +260,6 @@ def __init__( self, canvas, num ):
if matplotlib.is_interactive():
self.window.show()
- # attach a show method to the figure for pylab ease of use
- self.canvas.figure.show = lambda *args: self.window.show()
-
def notify_axes_change( fig ):
# This will be called whenever the current axes is changed
if self.toolbar != None: self.toolbar.update()
@@ -330,7 +327,7 @@ def _init_toolbar( self ):
continue
fname = os.path.join(basedir, image_file + '.ppm')
- image = qt.QPixmap()
+ image = qt.QPixmap()
image.load( fname )
button = qt.QPushButton( qt.QIconSet( image ), "", self )
View
3  lib/matplotlib/backends/backend_qt4.py
@@ -435,9 +435,6 @@ def __init__( self, canvas, num ):
if matplotlib.is_interactive():
self.window.show()
- # attach a show method to the figure for pylab ease of use
- self.canvas.figure.show = lambda *args: self.window.show()
-
def notify_axes_change( fig ):
# This will be called whenever the current axes is changed
if self.toolbar is not None:
View
43 lib/matplotlib/backends/backend_tkagg.py
@@ -85,7 +85,7 @@ def new_figure_manager_given_figure(num, figure):
"""
_focus = windowing.FocusManager()
window = Tk.Tk()
-
+
if Tk.TkVersion >= 8.5:
# put a mpl icon on the window rather than the default tk icon. Tkinter
# 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):
except:
# log the failure, but carry on
verbose.report('Could not load matplotlib icon: %s' % sys.exc_info()[1])
-
+
canvas = FigureCanvasTkAgg(figure, master=window)
figManager = FigureManagerTkAgg(canvas, num, window)
if matplotlib.is_interactive():
@@ -199,7 +199,7 @@ class FigureCanvasTkAgg(FigureCanvasAgg):
65439 : 'dec',
65421 : 'enter',
}
-
+
_keycode_lookup = {
262145: 'control',
524320: 'alt',
@@ -254,7 +254,7 @@ def filter_destroy(evt):
self._master = master
self._tkcanvas.focus_set()
-
+
def resize(self, event):
width, height = event.width, event.height
if self._resize_callback is not None:
@@ -443,31 +443,31 @@ def _get_key(self, event):
key = chr(val)
else:
key = None
-
- # add modifier keys to the key string. Bit details originate from
+
+ # add modifier keys to the key string. Bit details originate from
# http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
- # BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004;
- # BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080;
+ # BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004;
+ # BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080;
# BIT_MB_1 = 0x100; BIT_MB_2 = 0x200; BIT_MB_3 = 0x400;
- # In general, the modifier key is excluded from the modifier flag,
- # however this is not the case on "darwin", so double check that
+ # In general, the modifier key is excluded from the modifier flag,
+ # however this is not the case on "darwin", so double check that
# we aren't adding repeat modifier flags to a modifier key.
- modifiers = [(6, 'super', 'super'),
- (3, 'alt', 'alt'),
+ modifiers = [(6, 'super', 'super'),
+ (3, 'alt', 'alt'),
(2, 'ctrl', 'control'),
]
if sys.platform == 'darwin':
- modifiers = [(3, 'super', 'super'),
- (4, 'alt', 'alt'),
+ modifiers = [(3, 'super', 'super'),
+ (4, 'alt', 'alt'),
(2, 'ctrl', 'control'),
]
-
+
if key is not None:
# note, shift is not added to the keys as this is already accounted for
for bitmask, prefix, key_name in modifiers:
- if event.state & (1 << bitmask) and key_name not in key:
+ if event.state & (1 << bitmask) and key_name not in key:
key = '{}+{}'.format(prefix, key)
-
+
return key
def key_press(self, event):
@@ -542,9 +542,6 @@ def notify_axes_change(fig):
if self.toolbar != None: self.toolbar.update()
self.canvas.figure.add_axobserver(notify_axes_change)
- # attach a show method to the figure for pylab ease of use
- self.canvas.figure.show = lambda *args: self.show()
-
def resize(self, width, height=None):
# before 09-12-22, the resize method takes a single *event*
# parameter. On the other hand, the resize method of other
@@ -852,14 +849,14 @@ def _init_toolbar(self):
for text, tooltip_text, image_file, callback in self.toolitems:
if text is None:
- # spacer, unhandled in Tk
+ # spacer, unhandled in Tk
pass
else:
button = self._Button(text=text, file=image_file,
command=getattr(self, callback))
if tooltip_text is not None:
ToolTip.createToolTip(button, tooltip_text)
-
+
self.message = Tk.StringVar(master=self)
self._message_label = Tk.Label(master=self, textvariable=self.message)
self._message_label.pack(side=Tk.RIGHT)
@@ -954,7 +951,7 @@ def leave(event):
toolTip.hidetip()
widget.bind('<Enter>', enter)
widget.bind('<Leave>', leave)
-
+
def __init__(self, widget):
self.widget = widget
self.tipwindow = None
View
18 lib/matplotlib/backends/backend_wx.py
@@ -778,8 +778,8 @@ def Copy_to_Clipboard(self, event=None):
"copy bitmap of canvas to system clipboard"
bmp_obj = wx.BitmapDataObject()
bmp_obj.SetBitmap(self.bitmap)
-
- if not wx.TheClipboard.IsOpened():
+
+ if not wx.TheClipboard.IsOpened():
open_success = wx.TheClipboard.Open()
if open_success:
wx.TheClipboard.SetData(bmp_obj)
@@ -1251,7 +1251,7 @@ def _get_key(self, evt):
key = None
for meth, prefix in (
- [evt.AltDown, 'alt'],
+ [evt.AltDown, 'alt'],
[evt.ControlDown, 'ctrl'], ):
if meth():
key = '{}+{}'.format(prefix, key)
@@ -1421,7 +1421,7 @@ def _create_wx_app():
# retain a reference to the app object so it does not get garbage
# collected and cause segmentation faults
_create_wx_app.theWxApp = wxapp
-
+
def draw_if_interactive():
"""
@@ -1521,7 +1521,7 @@ def __init__(self, num, fig):
self.Fit()
self.canvas.SetMinSize((2, 2))
-
+
# give the window a matplotlib icon rather than the stock one.
# This is not currently working on Linux and is untested elsewhere.
#icon_path = os.path.join(matplotlib.rcParams['datapath'],
@@ -1603,12 +1603,6 @@ def notify_axes_change(fig):
if self.tb != None: self.tb.update()
self.canvas.figure.add_axobserver(notify_axes_change)
- def showfig(*args):
- frame.Show()
-
- # attach a show method to the figure
- self.canvas.figure.show = showfig
-
def show(self):
self.frame.Show()
@@ -1882,7 +1876,7 @@ def save_figure(self, *args):
os.path.join(dirname, filename), format=format)
except Exception as e:
error_msg_wx(str(e))
-
+
def set_cursor(self, cursor):
cursor =wx.StockCursor(cursord[cursor])
self.canvas.SetCursor( cursor )
View
26 lib/matplotlib/figure.py
@@ -42,7 +42,7 @@
from matplotlib.text import Text, _process_text_args
from matplotlib.transforms import (Affine2D, Bbox, BboxTransformTo,
TransformedBbox)
-
+from matplotlib.backend_bases import NonGuiException
docstring.interpd.update(projection_names = get_projection_names())
@@ -338,6 +338,26 @@ def _setup_canvas(self):
backend_mod = mbackends.pylab_setup()[0]
return backend_mod.FigureCanvas(self)
+ def show(self, warn=True):
+ """
+ If using a GUI backend, display the figure window.
+
+ For non-GUI backends, this does nothing, in which case
+ a warning will be issued if *warn* is True.
+ """
+ manager = getattr(self.canvas, 'manager')
+ if manager is not None:
+ try:
+ manager.show()
+ return
+ except NonGuiException:
+ pass
+ if warn:
+ import warnings
+ warnings.warn(
+ "matplotlib is currently using a non-GUI backend, "
+ "so cannot show the figure")
+
def _get_axes(self):
return self._axstack.as_list()
@@ -1188,10 +1208,10 @@ def __getstate__(self):
# and re-attached to another.
for attr_to_pop in ('_axobservers', 'show', 'canvas', '_cachedRenderer') :
state.pop(attr_to_pop, None)
-
+
# add version information to the state
state['__mpl_version__'] = _mpl_version
-
+
# check to see if the figure has a manager and whether it is registered
# with pyplot
if getattr(self.canvas, 'manager', None) is not None:
Something went wrong with that request. Please try again.