我刚刚在Python中用Tkinter创建了一个饼图,如下所示:
def frac(n):
return 360. * n / 500
import Tkinter
c = Tkinter.Canvas(width=100, height=100); c.pack()
c.create_arc((2,2,98,98), fill="red", start=frac(0), extent =
frac(100))
c.create_arc((2,2,98,98), fill="blue", start=frac(100), extent = frac(400))
c.create_arc((2,2,98,98), fill="white", start=frac(400), extent = frac(100), width=0)
c.mainloop()
结果如下:
现在,我希望在将鼠标悬停在每个切片上时更改每个切片的颜色。我怎样才能做到这一点?非常感谢
答案 0 :(得分:1)
所以,我的代码很乱,但我希望它能帮助你开始并获得基本的想法。
第一个想法是你需要将<Motion>
鼠标事件绑定到c
画布。
bind
方法有两个参数:一个事件,它说什么时候做什么,一个函数,它说明要做什么。
我选择定义一个redraw_chart
函数,根据鼠标的位置绘制饼图。
这个函数将在<Motion>
事件上调用,所以我绑定如下:
c.bind('<Motion>', lambda e: redraw_chart(e.x, e.y))
lambda
函数只是一个匿名函数,它接收引发的事件,并将事件的两个坐标(即鼠标的坐标)传递给redraw_chart
。
redraw_chart
函数非常愚蠢:它根据收到的坐标绘制饼图:
def redraw_chart(x, y):
global redCode, blueCode, whiteCode
arc = get_arc(x, y)
if arc == "red":
c.itemconfig(redCode, fill="green")
c.itemconfig(redCode, fill="blue")
c.itemconfig(redCode, fill="white")
elif arc == "blue":
c.itemconfig(redCode, fill="red")
c.itemconfig(redCode, fill="green")
c.itemconfig(redCode, fill="white")
elif arc == "white":
c.itemconfig(redCode, fill="red")
c.itemconfig(redCode, fill="blue")
c.itemconfig(redCode, fill="green")
else:
c.itemconfig(redCode, fill="green")
c.itemconfig(redCode, fill="blue")
c.itemconfig(redCode, fill="white")
现在,redCode
,blueCode
和whiteCode
是什么?
它们是c.create_arc
方法创建的三个弧对象的地址。
它们对修改弧非常有用,以避免创建新的弧。
还有一件事要定义:get_arc
函数。
get_arc
函数采用(x, y)
对,表示画布的一个点,并返回相应的弧:
def get_arc(x, y):
if is_in_arc(x, y, redArc[0], redArc[0]+redArc[1]):
return "red"
elif is_in_arc(x, y, blueArc[0], blueArc[0]+blueArc[1]):
return "blue"
elif is_in_arc(x, y, whiteArc[0], whiteArc[0]+whiteArc[1]):
return "white"
else:
return None
它依赖于is_in_arc
函数,它接受一个点,一部分饼,并告诉该点是否位于该部分。
def is_in_arc(x, y, angle0, angle1):
if (x-50)**2 + (y-50)**2 > 48**2:
return False
theta = - np.arctan2(y-50, x-50)
return angle0 <= frac(theta) <= angle1
来自np.arctan2
的{{1}}函数返回与numpy
点对应的弧度角度。
然后,(x, y)
方法以度为单位返回相应的值。
我修改了它,因为我真的不了解你的:
fract
所以这就是它的样子。您无法在屏幕截图中看到光标,但我保证在悬停时部件会变为绿色。
以下是完整的代码:
def frac(n):
if n < 0:
n += 2*np.pi
return 360 * n / (2*np.pi)
答案 1 :(得分:0)
您可以使用bind
方法绑定事件并重绘图表,如下所示:
def on_enter(event):
c.create_arc((2,2,98,98), fill="orange", start=frac(100), extent = frac(400))
(...)
c.bind('<Enter>', on_enter)
有关如何将整个内容嵌入到类中的示例,请参阅this answer。