@@ -152,7 +152,7 @@ class Button(AxesWidget):
152152 """
153153
154154 def __init__ (self , ax , label , image = None ,
155- color = '0.85' , hovercolor = '0.95' ):
155+ color = '0.85' , hovercolor = '0.95' , * , useblit = True ):
156156 """
157157 Parameters
158158 ----------
@@ -167,6 +167,9 @@ def __init__(self, ax, label, image=None,
167167 The color of the button when not activated.
168168 hovercolor : color
169169 The color of the button when the mouse is over it.
170+ useblit : bool, default: True
171+ Use blitting for faster drawing if supported by the backend.
172+ See the tutorial :doc:`/tutorials/advanced/blitting` for details.
170173 """
171174 super ().__init__ (ax )
172175
@@ -177,6 +180,8 @@ def __init__(self, ax, label, image=None,
177180 horizontalalignment = 'center' ,
178181 transform = ax .transAxes )
179182
183+ self ._useblit = useblit and self .canvas .supports_blit
184+
180185 self ._observers = cbook .CallbackRegistry (signals = ["clicked" ])
181186
182187 self .connect_event ('button_press_event' , self ._click )
@@ -209,7 +214,11 @@ def _motion(self, event):
209214 if not colors .same_color (c , self .ax .get_facecolor ()):
210215 self .ax .set_facecolor (c )
211216 if self .drawon :
212- self .ax .figure .canvas .draw ()
217+ if self ._useblit :
218+ self .ax .draw_artist (self .ax )
219+ self .canvas .blit (self .ax .bbox )
220+ else :
221+ self .canvas .draw ()
213222
214223 def on_clicked (self , func ):
215224 """
@@ -968,6 +977,7 @@ class CheckButtons(AxesWidget):
968977 ----------
969978 ax : `~matplotlib.axes.Axes`
970979 The parent Axes for the widget.
980+
971981 labels : list of `.Text`
972982
973983 rectangles : list of `.Rectangle`
@@ -977,21 +987,22 @@ class CheckButtons(AxesWidget):
977987 each box, but have ``set_visible(False)`` when its box is not checked.
978988 """
979989
980- def __init__ (self , ax , labels , actives = None ):
990+ def __init__ (self , ax , labels , actives = None , * , useblit = True ):
981991 """
982992 Add check buttons to `matplotlib.axes.Axes` instance *ax*.
983993
984994 Parameters
985995 ----------
986996 ax : `~matplotlib.axes.Axes`
987997 The parent Axes for the widget.
988-
989998 labels : list of str
990999 The labels of the check buttons.
991-
9921000 actives : list of bool, optional
9931001 The initial check states of the buttons. The list must have the
9941002 same length as *labels*. If not given, all buttons are unchecked.
1003+ useblit : bool, default: True
1004+ Use blitting for faster drawing if supported by the backend.
1005+ See the tutorial :doc:`/tutorials/advanced/blitting` for details.
9951006 """
9961007 super ().__init__ (ax )
9971008
@@ -1002,6 +1013,9 @@ def __init__(self, ax, labels, actives=None):
10021013 if actives is None :
10031014 actives = [False ] * len (labels )
10041015
1016+ self ._useblit = useblit and self .canvas .supports_blit
1017+ self ._background = None
1018+
10051019 ys = np .linspace (1 , 0 , len (labels )+ 2 )[1 :- 1 ]
10061020 text_size = mpl .rcParams ["font.size" ] / 2
10071021
@@ -1017,13 +1031,26 @@ def __init__(self, ax, labels, actives=None):
10171031 self ._crosses = ax .scatter (
10181032 [0.15 ] * len (ys ), ys , marker = 'x' , linewidth = 1 , s = text_size ** 2 ,
10191033 c = ["k" if active else "none" for active in actives ],
1020- transform = ax .transAxes
1034+ transform = ax .transAxes , animated = self . _useblit ,
10211035 )
10221036
10231037 self .connect_event ('button_press_event' , self ._clicked )
1038+ if self ._useblit :
1039+ self .connect_event ('draw_event' , self ._clear )
10241040
10251041 self ._observers = cbook .CallbackRegistry (signals = ["clicked" ])
10261042
1043+ def _clear (self , event ):
1044+ """Internal event handler to clear the buttons."""
1045+ if self .ignore (event ):
1046+ return
1047+ self ._background = self .canvas .copy_from_bbox (self .ax .bbox )
1048+ self .ax .draw_artist (self ._crosses )
1049+ if hasattr (self , '_lines' ):
1050+ for l1 , l2 in self ._lines :
1051+ self .ax .draw_artist (l1 )
1052+ self .ax .draw_artist (l2 )
1053+
10271054 def _clicked (self , event ):
10281055 if self .ignore (event ) or event .button != 1 or event .inaxes != self .ax :
10291056 return
@@ -1084,7 +1111,17 @@ def set_active(self, index):
10841111 l2 .set_visible (not l2 .get_visible ())
10851112
10861113 if self .drawon :
1087- self .ax .figure .canvas .draw ()
1114+ if self ._useblit :
1115+ if self ._background is not None :
1116+ self .canvas .restore_region (self ._background )
1117+ self .ax .draw_artist (self ._crosses )
1118+ if hasattr (self , "_lines" ):
1119+ for l1 , l2 in self ._lines :
1120+ self .ax .draw_artist (l1 )
1121+ self .ax .draw_artist (l2 )
1122+ self .canvas .blit (self .ax .bbox )
1123+ else :
1124+ self .canvas .draw ()
10881125
10891126 if self .eventson :
10901127 self ._observers .process ('clicked' , self .labels [index ].get_text ())
@@ -1143,7 +1180,8 @@ def lines(self):
11431180 current_status = self .get_status ()
11441181 lineparams = {'color' : 'k' , 'linewidth' : 1.25 ,
11451182 'transform' : self .ax .transAxes ,
1146- 'solid_capstyle' : 'butt' }
1183+ 'solid_capstyle' : 'butt' ,
1184+ 'animated' : self ._useblit }
11471185 for i , y in enumerate (ys ):
11481186 x , y = 0.05 , y - h / 2
11491187 l1 = Line2D ([x , x + w ], [y + h , y ], ** lineparams )
@@ -1447,7 +1485,8 @@ class RadioButtons(AxesWidget):
14471485 The label text of the currently selected button.
14481486 """
14491487
1450- def __init__ (self , ax , labels , active = 0 , activecolor = 'blue' ):
1488+ def __init__ (self , ax , labels , active = 0 , activecolor = 'blue' , * ,
1489+ useblit = True ):
14511490 """
14521491 Add radio buttons to an `~.axes.Axes`.
14531492
@@ -1461,6 +1500,9 @@ def __init__(self, ax, labels, active=0, activecolor='blue'):
14611500 The index of the initially selected button.
14621501 activecolor : color
14631502 The color of the selected button.
1503+ useblit : bool, default: True
1504+ Use blitting for faster drawing if supported by the backend.
1505+ See the tutorial :doc:`/tutorials/advanced/blitting` for details.
14641506 """
14651507 super ().__init__ (ax )
14661508 self .activecolor = activecolor
@@ -1473,19 +1515,34 @@ def __init__(self, ax, labels, active=0, activecolor='blue'):
14731515 ys = np .linspace (1 , 0 , len (labels ) + 2 )[1 :- 1 ]
14741516 text_size = mpl .rcParams ["font.size" ] / 2
14751517
1518+ self ._useblit = useblit and self .canvas .supports_blit
1519+ self ._background = None
1520+
14761521 self .labels = [
14771522 ax .text (0.25 , y , label , transform = ax .transAxes ,
14781523 horizontalalignment = "left" , verticalalignment = "center" )
14791524 for y , label in zip (ys , labels )]
14801525 self ._buttons = ax .scatter (
14811526 [.15 ] * len (ys ), ys , transform = ax .transAxes , s = text_size ** 2 ,
14821527 c = [activecolor if i == active else "none" for i in range (len (ys ))],
1483- edgecolor = "black" )
1528+ edgecolor = "black" , animated = self . _useblit )
14841529
14851530 self .connect_event ('button_press_event' , self ._clicked )
1531+ if self ._useblit :
1532+ self .connect_event ('draw_event' , self ._clear )
14861533
14871534 self ._observers = cbook .CallbackRegistry (signals = ["clicked" ])
14881535
1536+ def _clear (self , event ):
1537+ """Internal event handler to clear the buttons."""
1538+ if self .ignore (event ):
1539+ return
1540+ self ._background = self .canvas .copy_from_bbox (self .ax .bbox )
1541+ self .ax .draw_artist (self ._buttons )
1542+ if hasattr (self , "_circles" ):
1543+ for circle in self ._circles :
1544+ self .ax .draw_artist (circle )
1545+
14891546 def _clicked (self , event ):
14901547 if self .ignore (event ) or event .button != 1 or event .inaxes != self .ax :
14911548 return
@@ -1524,8 +1581,20 @@ def set_active(self, index):
15241581 if hasattr (self , "_circles" ): # Remove once circles is removed.
15251582 for i , p in enumerate (self ._circles ):
15261583 p .set_facecolor (self .activecolor if i == index else "none" )
1584+ if self .drawon and self ._useblit :
1585+ self .ax .draw_artist (p )
15271586 if self .drawon :
1528- self .ax .figure .canvas .draw ()
1587+ if self ._useblit :
1588+ if self ._background is not None :
1589+ self .canvas .restore_region (self ._background )
1590+ self .ax .draw_artist (self ._buttons )
1591+ if hasattr (self , "_circles" ):
1592+ for p in self ._circles :
1593+ self .ax .draw_artist (p )
1594+ self .canvas .blit (self .ax .bbox )
1595+ else :
1596+ self .canvas .draw ()
1597+
15291598 if self .eventson :
15301599 self ._observers .process ('clicked' , self .labels [index ].get_text ())
15311600
@@ -1549,7 +1618,8 @@ def circles(self):
15491618 circles = self ._circles = [
15501619 Circle (xy = self ._buttons .get_offsets ()[i ], edgecolor = "black" ,
15511620 facecolor = self ._buttons .get_facecolor ()[i ],
1552- radius = radius , transform = self .ax .transAxes )
1621+ radius = radius , transform = self .ax .transAxes ,
1622+ animated = self ._useblit )
15531623 for i in range (len (self .labels ))]
15541624 self ._buttons .set_visible (False )
15551625 for circle in circles :
0 commit comments