![](/img/trans.png)
[英]How to display an annotation and exploding a wedge when hovering over pie chart?
[英]change color of a pie chart when hovering mouse over it
我剛剛在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()
這是結果:
現在,我希望在將鼠標懸停在每個切片上時更改每個切片的顏色。 我怎樣才能做到這一點? 非常感謝
所以,我的代碼很亂,但我希望它能幫助你開始並獲得基本的想法。
第一個想法是您需要將<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
來自numpy
的np.arctan2
函數返回對應於(x, y)
點的弧度角度。 然后, fract
方法以度為單位返回相應的值。 我修改了它,因為我真的不了解你的:
def frac(n):
if n < 0:
n += 2*np.pi
return 360 * n / (2*np.pi)
所以這就是它的樣子。 您無法在屏幕截圖中看到光標,但我保證在懸停時部件會變為綠色。
這是完整的代碼:
import tkinter as tk
import numpy as np
def frac(n):
if n < 0:
n += 2*np.pi
return 360 * n / (2*np.pi)
c = tk.Canvas(width=100, height=100)
c.pack()
redArc = (frac(0), frac(np.pi/3))
blueArc = (frac(np.pi/3), frac(4*np.pi/3))
whiteArc = (frac(5*np.pi/3), frac(np.pi/3))
redCode = c.create_arc((2,2,98,98), fill="red", start=redArc[0], extent=redArc[1])
blueCode = c.create_arc((2,2,98,98), fill="blue", start=blueArc[0], extent=blueArc[1])
whiteCode = c.create_arc((2,2,98,98), fill="white", start=whiteArc[0], extent=whiteArc[1])
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
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
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")
c.bind('<Motion>', lambda e: redraw_chart(e.x, e.y))
c.mainloop()
您可以使用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)
有關如何將整個事物嵌入到類中的示例,請參閱此答案 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.