Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit26580cc

Browse files
committed
Draw RadioButtons using scatter to ensure circular buttons.
To ensure backcompat without bothering the majority of users who don'tactually access the .circles attribute, dynamically (and irreversibly)switch back to the old draw method (list of Circles) whenever thatattribute is accessed for the first time (if ever).
1 parent1fa7467 commit26580cc

File tree

3 files changed

+50
-45
lines changed

3 files changed

+50
-45
lines changed
Binary file not shown.

‎lib/matplotlib/tests/test_widgets.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,18 +1003,21 @@ def test_check_radio_buttons_image():
10031003
plt.subplots_adjust(left=0.3)
10041004
rax1=plt.axes([0.05,0.7,0.15,0.15])
10051005
rax2=plt.axes([0.05,0.2,0.15,0.15])
1006-
widgets.RadioButtons(rax1, ('Radio 1','Radio 2','Radio 3'))
1006+
rb=widgets.RadioButtons(rax1, ('Radio 1','Radio 2','Radio 3'))
1007+
withpytest.warns(DeprecationWarning):
1008+
rb.circles# Trigger the old-style elliptic radiobuttons.
10071009
widgets.CheckButtons(rax2, ('Check 1','Check 2','Check 3'),
10081010
(False,True,True))
10091011

10101012

1011-
@image_comparison(['check_bunch_of_radio_buttons.png'],
1012-
style='mpl20',remove_text=True)
1013-
deftest_check_bunch_of_radio_buttons():
1014-
rax=plt.axes([0.05,0.1,0.15,0.7])
1015-
widgets.RadioButtons(rax, ('B1','B2','B3','B4','B5','B6',
1016-
'B7','B8','B9','B10','B11','B12',
1017-
'B13','B14','B15'))
1013+
@check_figures_equal(extensions=["png"])
1014+
deftest_radio_buttons(fig_test,fig_ref):
1015+
widgets.RadioButtons(fig_test.subplots(), ["tea","coffee"])
1016+
ax=fig_ref.add_subplot(xticks=[],yticks=[])
1017+
ax.scatter([.15,.15], [2/3,1/3],transform=ax.transAxes,
1018+
s=(plt.rcParams["font.size"]/2)**2,c=["C0","none"])
1019+
ax.text(.25,2/3,"tea",transform=ax.transAxes,va="center")
1020+
ax.text(.25,1/3,"coffee",transform=ax.transAxes,va="center")
10181021

10191022

10201023
deftest_slider_slidermin_slidermax_invalid():

‎lib/matplotlib/widgets.py

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,41 +1404,25 @@ 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()
14161412

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)
1413+
ys=np.linspace(1,0,len(labels)+2)[1:-1]
1414+
text_size=mpl.rcParams["font.size"]/2
14211415

14221416
self.labels= []
1423-
self.circles= []
14241417
fory,labelinzip(ys,labels):
14251418
t=ax.text(0.25,y,label,transform=ax.transAxes,
14261419
horizontalalignment='left',
14271420
verticalalignment='center')
1428-
1429-
ifcnt==active:
1430-
self.value_selected=label
1431-
facecolor=activecolor
1432-
else:
1433-
facecolor=axcolor
1434-
1435-
p=Circle(xy=(0.15,y),radius=circle_radius,edgecolor='black',
1436-
facecolor=facecolor,transform=ax.transAxes)
1437-
14381421
self.labels.append(t)
1439-
self.circles.append(p)
1440-
ax.add_patch(p)
1441-
cnt+=1
1422+
self._buttons=ax.scatter(
1423+
[.15]*len(ys),ys,transform=ax.transAxes,s=text_size**2,
1424+
c=[activecolorifi==activeelse"none"foriinrange(len(ys))],
1425+
edgecolor="black")
14421426

14431427
self.connect_event('button_press_event',self._clicked)
14441428

@@ -1448,11 +1432,20 @@ def _clicked(self, event):
14481432
ifself.ignore(event)orevent.button!=1orevent.inaxes!=self.ax:
14491433
return
14501434
pclicked=self.ax.transAxes.inverted().transform((event.x,event.y))
1435+
_,inds=self._buttons.contains(event)
1436+
coords=self._buttons.get_offset_transform().transform(
1437+
self._buttons.get_offsets())
14511438
distances= {}
1452-
fori, (p,t)inenumerate(zip(self.circles,self.labels)):
1453-
if (t.get_window_extent().contains(event.x,event.y)
1454-
ornp.linalg.norm(pclicked-p.center)<p.radius):
1455-
distances[i]=np.linalg.norm(pclicked-p.center)
1439+
ifhasattr(self,"_circles"):# Remove once circles is removed.
1440+
fori, (p,t)inenumerate(zip(self._circles,self.labels)):
1441+
if (t.get_window_extent().contains(event.x,event.y)
1442+
ornp.linalg.norm(pclicked-p.center)<p.radius):
1443+
distances[i]=np.linalg.norm(pclicked-p.center)
1444+
else:
1445+
fori,tinenumerate(self.labels):
1446+
if (iininds["ind"]
1447+
ort.get_window_extent().contains(event.x,event.y)):
1448+
distances[i]=np.linalg.norm(pclicked-coords[i])
14561449
iflen(distances)>0:
14571450
closest=min(distances,key=distances.get)
14581451
self.set_active(closest)
@@ -1465,19 +1458,14 @@ def set_active(self, index):
14651458
"""
14661459
ifindexnotinrange(len(self.labels)):
14671460
raiseValueError(f'Invalid RadioButton index:{index}')
1468-
14691461
self.value_selected=self.labels[index].get_text()
1470-
1471-
fori,pinenumerate(self.circles):
1472-
ifi==index:
1473-
color=self.activecolor
1474-
else:
1475-
color=self.ax.get_facecolor()
1476-
p.set_facecolor(color)
1477-
1462+
self._buttons.get_facecolor()[:]=colors.to_rgba("none")
1463+
self._buttons.get_facecolor()[index]=colors.to_rgba(self.activecolor)
1464+
ifhasattr(self,"_circles"):# Remove once circles is removed.
1465+
fori,pinenumerate(self._circles):
1466+
p.set_facecolor(self.activecolorifi==indexelse"none")
14781467
ifself.drawon:
14791468
self.ax.figure.canvas.draw()
1480-
14811469
ifself.eventson:
14821470
self._observers.process('clicked',self.labels[index].get_text())
14831471

@@ -1493,6 +1481,20 @@ def disconnect(self, cid):
14931481
"""Remove the observer with connection id *cid*."""
14941482
self._observers.disconnect(cid)
14951483

1484+
@_api.deprecated("3.7")
1485+
@property
1486+
defcircles(self):
1487+
radius=min(.5/ (len(self.labels)+1)-.01,.05)
1488+
circles=self._circles= [
1489+
Circle(xy=self._buttons.get_offsets()[i],edgecolor="black",
1490+
facecolor=self._buttons.get_facecolor()[i],
1491+
radius=radius,transform=self.ax.transAxes)
1492+
foriinrange(len(self.labels)) ]
1493+
self._buttons.set_visible(False)
1494+
forcircleinself._circles:
1495+
self.ax.add_patch(circle)
1496+
returncircles
1497+
14961498

14971499
classSubplotTool(Widget):
14981500
"""

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp