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

Skip to content

Commit 0944dcb

Browse files
committed
Only set the wait cursor if the last draw was >1s ago.
This avoids setting the wait cursor when panning or zooming (that behavior was somewhat annoying), or during an animation that renders at least one frame per second. Rename `_set_cursor` to `_update_cursor` as it is fairly different from `set_cursor` and the previous name could cause confusion. Move the defintion of cursor-related methods to a single place.
1 parent 155f7b7 commit 0944dcb

File tree

3 files changed

+54
-18
lines changed

3 files changed

+54
-18
lines changed

lib/matplotlib/backend_bases.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2342,11 +2342,11 @@ def key_press_handler(event, canvas, toolbar=None):
23422342
# pan mnemonic (default key 'p')
23432343
elif event.key in pan_keys:
23442344
toolbar.pan()
2345-
toolbar._set_cursor(event)
2345+
toolbar._update_cursor(event)
23462346
# zoom mnemonic (default key 'o')
23472347
elif event.key in zoom_keys:
23482348
toolbar.zoom()
2349-
toolbar._set_cursor(event)
2349+
toolbar._update_cursor(event)
23502350
# saving current figure (default key 's')
23512351
elif event.key in save_keys:
23522352
toolbar.save_figure()
@@ -2700,7 +2700,10 @@ class implementation.
27002700
"""
27012701
raise NotImplementedError
27022702

2703-
def _set_cursor(self, event):
2703+
def _update_cursor(self, event):
2704+
"""
2705+
Update the cursor after a mouse move event or a tool (de)activation.
2706+
"""
27042707
if not event.inaxes or not self._active:
27052708
if self._lastCursor != cursors.POINTER:
27062709
self.set_cursor(cursors.POINTER)
@@ -2715,8 +2718,30 @@ def _set_cursor(self, event):
27152718
self.set_cursor(cursors.MOVE)
27162719
self._lastCursor = cursors.MOVE
27172720

2721+
@contextmanager
2722+
def _wait_cursor_for_draw_cm(self):
2723+
"""
2724+
Set the cursor to a wait cursor when drawing the canvas.
2725+
2726+
In order to avoid constantly changing the cursor when the canvas
2727+
changes frequently, do nothing if this context was triggered during the
2728+
last second. (Optimally we'd prefer only setting the wait cursor if
2729+
the *current* draw takes too long, but the current draw blocks the GUI
2730+
thread).
2731+
"""
2732+
self._draw_time, last_draw_time = (
2733+
time.time(), getattr(self, "_draw_time", -np.inf))
2734+
if self._draw_time - last_draw_time > 1:
2735+
try:
2736+
self.set_cursor(cursors.WAIT)
2737+
yield
2738+
finally:
2739+
self.set_cursor(self._lastCursor)
2740+
else:
2741+
yield
2742+
27182743
def mouse_move(self, event):
2719-
self._set_cursor(event)
2744+
self._update_cursor(event)
27202745

27212746
if event.inaxes and event.inaxes.get_navigate():
27222747

lib/matplotlib/backends/backend_agg.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,14 @@
2323
import threading
2424
except ImportError:
2525
import dummy_threading as threading
26-
import numpy as np
26+
try:
27+
from contextlib import nullcontext
28+
except ImportError:
29+
from contextlib import ExitStack as nullcontext # Py 3.6.
2730
from math import radians, cos, sin
31+
32+
import numpy as np
33+
2834
from matplotlib import cbook, rcParams, __version__
2935
from matplotlib.backend_bases import (
3036
_Backend, FigureCanvasBase, FigureManagerBase, RendererBase)
@@ -383,7 +389,10 @@ def draw(self):
383389
Draw the figure using the renderer.
384390
"""
385391
self.renderer = self.get_renderer(cleared=True)
386-
with RendererAgg.lock:
392+
# Acquire a lock on the shared font cache.
393+
with RendererAgg.lock, \
394+
(self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
395+
else nullcontext()):
387396
self.figure.draw(self.renderer)
388397
# A GUI class may be need to update a window using this draw, so
389398
# don't forget to call the superclass.

lib/matplotlib/backends/backend_gtk3cairo.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
try:
2+
from contextlib import nullcontext
3+
except ImportError:
4+
from contextlib import ExitStack as nullcontext # Py 3.6.
5+
16
from . import backend_cairo, backend_gtk3
27
from .backend_gtk3 import Gtk, _BackendGTK3
38
from matplotlib import cbook
@@ -22,18 +27,15 @@ def _render_figure(self, width, height):
2227

2328
def on_draw_event(self, widget, ctx):
2429
"""GtkDrawable draw event."""
25-
# toolbar = self.toolbar
26-
# if toolbar:
27-
# toolbar.set_cursor(cursors.WAIT)
28-
self._renderer.set_context(ctx)
29-
allocation = self.get_allocation()
30-
Gtk.render_background(
31-
self.get_style_context(), ctx,
32-
allocation.x, allocation.y, allocation.width, allocation.height)
33-
self._render_figure(allocation.width, allocation.height)
34-
# if toolbar:
35-
# toolbar.set_cursor(toolbar._lastCursor)
36-
return False # finish event propagation?
30+
with (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
31+
else nullcontext()):
32+
self._renderer.set_context(ctx)
33+
allocation = self.get_allocation()
34+
Gtk.render_background(
35+
self.get_style_context(), ctx,
36+
allocation.x, allocation.y,
37+
allocation.width, allocation.height)
38+
self._render_figure(allocation.width, allocation.height)
3739

3840

3941
@cbook.deprecated("3.1", alternative="backend_gtk3.FigureManagerGTK3")

0 commit comments

Comments
 (0)