1+ import matplotlib .pyplot as plt
2+ import numpy as np
3+ import matplotlib
4+ matplotlib .use ('module://pygame_matplotlib.backend_pygame' )
5+
6+ class BlitManager :
7+ def __init__ (self , canvas , animated_artists = ()):
8+ """
9+ Parameters
10+ ----------
11+ canvas : FigureCanvasAgg
12+ The canvas to work with, this only works for sub-classes of the Agg
13+ canvas which have the `~FigureCanvasAgg.copy_from_bbox` and
14+ `~FigureCanvasAgg.restore_region` methods.
15+
16+ animated_artists : Iterable[Artist]
17+ List of the artists to manage
18+ """
19+ self .canvas = canvas
20+ self ._bg = None
21+ self ._artists = []
22+
23+ for a in animated_artists :
24+ self .add_artist (a )
25+ # grab the background on every draw
26+ self .cid = canvas .mpl_connect ("draw_event" , self .on_draw )
27+
28+ def on_draw (self , event ):
29+ """Callback to register with 'draw_event'."""
30+ cv = self .canvas
31+ if event is not None :
32+ if event .canvas != cv :
33+ raise RuntimeError
34+ self ._bg = cv .copy_from_bbox (cv .figure .bbox )
35+ self ._draw_animated ()
36+
37+ def add_artist (self , art ):
38+ """
39+ Add an artist to be managed.
40+
41+ Parameters
42+ ----------
43+ art : Artist
44+
45+ The artist to be added. Will be set to 'animated' (just
46+ to be safe). *art* must be in the figure associated with
47+ the canvas this class is managing.
48+
49+ """
50+ if art .figure != self .canvas .figure :
51+ raise RuntimeError
52+ art .set_animated (True )
53+ self ._artists .append (art )
54+
55+ def _draw_animated (self ):
56+ """Draw all of the animated artists."""
57+ fig = self .canvas .figure
58+ for a in self ._artists :
59+ fig .draw_artist (a )
60+
61+ def update (self ):
62+ """Update the screen with animated artists."""
63+ cv = self .canvas
64+ fig = cv .figure
65+ # paranoia in case we missed the draw event,
66+ if self ._bg is None :
67+ self .on_draw (None )
68+ else :
69+ # restore the background
70+ cv .restore_region (self ._bg )
71+ # draw all of the animated artists
72+ self ._draw_animated ()
73+ # update the GUI state
74+ cv .blit (fig .bbox )
75+ # let the GUI event loop process anything it has to do
76+ cv .flush_events ()
77+
78+ x = np .linspace (0 , 2 * np .pi , 100 )
79+ # make a new figure
80+ fig , ax = plt .subplots ()
81+ # add a line
82+ (ln ,) = ax .plot (x , np .sin (x ), animated = True )
83+ # add a frame number
84+ fr_number = ax .annotate (
85+ "0" ,
86+ (0 , 1 ),
87+ xycoords = "axes fraction" ,
88+ xytext = (10 , - 10 ),
89+ textcoords = "offset points" ,
90+ ha = "left" ,
91+ va = "top" ,
92+ animated = True ,
93+ )
94+ bm = BlitManager (fig .canvas , [ln , fr_number ])
95+ # make sure our window is on the screen and drawn
96+ plt .show (block = False )
97+ plt .pause (.1 )
98+
99+ for j in range (1000 ):
100+ # update the artists
101+ ln .set_ydata (np .sin (x + (j / 100 ) * np .pi ))
102+ fr_number .set_text ("frame: {j}" .format (j = j ))
103+ # tell the blitting manager to do its thing
104+ bm .update ()
0 commit comments