@@ -1404,41 +1404,23 @@ def __init__(self, ax, labels, active=0, activecolor='blue'):
14041404 """
14051405 super ().__init__ (ax )
14061406 self .activecolor = activecolor
1407- self .value_selected = None
1407+ self .value_selected = labels [ active ]
14081408
14091409 ax .set_xticks ([])
14101410 ax .set_yticks ([])
14111411 ax .set_navigate (False )
1412- dy = 1. / (len (labels ) + 1 )
1413- ys = np .linspace (1 - dy , dy , len (labels ))
1414- cnt = 0
1415- axcolor = ax .get_facecolor ()
1416-
1417- # scale the radius of the circle with the spacing between each one
1418- circle_radius = dy / 2 - 0.01
1419- # default to hard-coded value if the radius becomes too large
1420- circle_radius = min (circle_radius , 0.05 )
1421-
1422- self .labels = []
1423- self .circles = []
1424- for y , label in zip (ys , labels ):
1425- t = ax .text (0.25 , y , label , transform = ax .transAxes ,
1426- horizontalalignment = 'left' ,
1427- verticalalignment = 'center' )
14281412
1429- if cnt == active :
1430- self .value_selected = label
1431- facecolor = activecolor
1432- else :
1433- facecolor = axcolor
1413+ ys = np .linspace (1 , 0 , len (labels ) + 2 )[1 :- 1 ]
1414+ text_size = mpl .rcParams ["font.size" ] / 2
14341415
1435- p = Circle (xy = (0.15 , y ), radius = circle_radius , edgecolor = 'black' ,
1436- facecolor = facecolor , transform = ax .transAxes )
1437-
1438- self .labels .append (t )
1439- self .circles .append (p )
1440- ax .add_patch (p )
1441- cnt += 1
1416+ self .labels = [
1417+ ax .text (0.25 , y , label , transform = ax .transAxes ,
1418+ horizontalalignment = "left" , verticalalignment = "center" )
1419+ for y , label in zip (ys , labels )]
1420+ self ._buttons = ax .scatter (
1421+ [.15 ] * len (ys ), ys , transform = ax .transAxes , s = text_size ** 2 ,
1422+ c = [activecolor if i == active else "none" for i in range (len (ys ))],
1423+ edgecolor = "black" )
14421424
14431425 self .connect_event ('button_press_event' , self ._clicked )
14441426
@@ -1448,11 +1430,20 @@ def _clicked(self, event):
14481430 if self .ignore (event ) or event .button != 1 or event .inaxes != self .ax :
14491431 return
14501432 pclicked = self .ax .transAxes .inverted ().transform ((event .x , event .y ))
1433+ _ , inds = self ._buttons .contains (event )
1434+ coords = self ._buttons .get_offset_transform ().transform (
1435+ self ._buttons .get_offsets ())
14511436 distances = {}
1452- for i , (p , t ) in enumerate (zip (self .circles , self .labels )):
1453- if (t .get_window_extent ().contains (event .x , event .y )
1454- or np .linalg .norm (pclicked - p .center ) < p .radius ):
1455- distances [i ] = np .linalg .norm (pclicked - p .center )
1437+ if hasattr (self , "_circles" ): # Remove once circles is removed.
1438+ for i , (p , t ) in enumerate (zip (self ._circles , self .labels )):
1439+ if (t .get_window_extent ().contains (event .x , event .y )
1440+ or np .linalg .norm (pclicked - p .center ) < p .radius ):
1441+ distances [i ] = np .linalg .norm (pclicked - p .center )
1442+ else :
1443+ for i , t in enumerate (self .labels ):
1444+ if (i in inds ["ind" ]
1445+ or t .get_window_extent ().contains (event .x , event .y )):
1446+ distances [i ] = np .linalg .norm (pclicked - coords [i ])
14561447 if len (distances ) > 0 :
14571448 closest = min (distances , key = distances .get )
14581449 self .set_active (closest )
@@ -1465,19 +1456,14 @@ def set_active(self, index):
14651456 """
14661457 if index not in range (len (self .labels )):
14671458 raise ValueError (f'Invalid RadioButton index: { index } ' )
1468-
14691459 self .value_selected = self .labels [index ].get_text ()
1470-
1471- for i , p in enumerate (self .circles ):
1472- if i == index :
1473- color = self .activecolor
1474- else :
1475- color = self .ax .get_facecolor ()
1476- p .set_facecolor (color )
1477-
1460+ self ._buttons .get_facecolor ()[:] = colors .to_rgba ("none" )
1461+ self ._buttons .get_facecolor ()[index ] = colors .to_rgba (self .activecolor )
1462+ if hasattr (self , "_circles" ): # Remove once circles is removed.
1463+ for i , p in enumerate (self ._circles ):
1464+ p .set_facecolor (self .activecolor if i == index else "none" )
14781465 if self .drawon :
14791466 self .ax .figure .canvas .draw ()
1480-
14811467 if self .eventson :
14821468 self ._observers .process ('clicked' , self .labels [index ].get_text ())
14831469
@@ -1493,6 +1479,20 @@ def disconnect(self, cid):
14931479 """Remove the observer with connection id *cid*."""
14941480 self ._observers .disconnect (cid )
14951481
1482+ @_api .deprecated ("3.7" )
1483+ @property
1484+ def circles (self ):
1485+ radius = min (.5 / (len (self .labels ) + 1 ) - .01 , .05 )
1486+ circles = self ._circles = [
1487+ Circle (xy = self ._buttons .get_offsets ()[i ], edgecolor = "black" ,
1488+ facecolor = self ._buttons .get_facecolor ()[i ],
1489+ radius = radius , transform = self .ax .transAxes )
1490+ for i in range (len (self .labels ))]
1491+ self ._buttons .set_visible (False )
1492+ for circle in self ._circles :
1493+ self .ax .add_patch (circle )
1494+ return circles
1495+
14961496
14971497class SubplotTool (Widget ):
14981498 """
0 commit comments