@@ -1404,41 +1404,23 @@ def __init__(self, ax, labels, active=0, activecolor='blue'):
1404
1404
"""
1405
1405
super ().__init__ (ax )
1406
1406
self .activecolor = activecolor
1407
- self .value_selected = None
1407
+ self .value_selected = labels [ active ]
1408
1408
1409
1409
ax .set_xticks ([])
1410
1410
ax .set_yticks ([])
1411
1411
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' )
1428
1412
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
1434
1415
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" )
1442
1424
1443
1425
self .connect_event ('button_press_event' , self ._clicked )
1444
1426
@@ -1448,11 +1430,20 @@ def _clicked(self, event):
1448
1430
if self .ignore (event ) or event .button != 1 or event .inaxes != self .ax :
1449
1431
return
1450
1432
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 ())
1451
1436
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 ])
1456
1447
if len (distances ) > 0 :
1457
1448
closest = min (distances , key = distances .get )
1458
1449
self .set_active (closest )
@@ -1465,19 +1456,14 @@ def set_active(self, index):
1465
1456
"""
1466
1457
if index not in range (len (self .labels )):
1467
1458
raise ValueError (f'Invalid RadioButton index: { index } ' )
1468
-
1469
1459
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" )
1478
1465
if self .drawon :
1479
1466
self .ax .figure .canvas .draw ()
1480
-
1481
1467
if self .eventson :
1482
1468
self ._observers .process ('clicked' , self .labels [index ].get_text ())
1483
1469
@@ -1493,6 +1479,20 @@ def disconnect(self, cid):
1493
1479
"""Remove the observer with connection id *cid*."""
1494
1480
self ._observers .disconnect (cid )
1495
1481
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
+
1496
1496
1497
1497
class SubplotTool (Widget ):
1498
1498
"""
0 commit comments