简体   繁体   English

将鼠标悬停在饼图上时更改饼图的颜色

[英]change color of a pie chart when hovering mouse over it

I have just created a pie chart by Tkinter in Python as follows: 我刚刚在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()

This is the result: 这是结果:

在此输入图像描述

Now, I want to change the color of each slice when hovering the mouse over it. 现在,我希望在将鼠标悬停在每个切片上时更改每个切片的颜色。 How can I do that? 我怎样才能做到这一点? Many thanks 非常感谢

So, my code is a mess, but I hope it will help you get started and get the basic ideas. 所以,我的代码很乱,但我希望它能帮助你开始并获得基本的想法。

The first idea is that you need to bind the <Motion> mouse event to the c canvas. 第一个想法是您需要将<Motion>鼠标事件绑定到c画布。 The bind method takes two arguments: an event, which says when to do something, and a function, which says what to do. bind方法有两个参数:一个事件,它说什么时候做什么,一个函数,它说明要做什么。 I chose to define a redraw_chart function, that draws the pie according to the position of the mouse. 我选择定义一个redraw_chart函数,它根据鼠标的位置绘制饼图。 This function is what will be called on a <Motion> event, so I bind as follows: 这个函数将在<Motion>事件中调用,所以我绑定如下:

c.bind('<Motion>', lambda e: redraw_chart(e.x, e.y))

The lambda function is just an anonymous function, that receives the event raised, and passes the two coordinates of the event (that is, the coordinates of the mouse) to the redraw_chart . lambda函数只是一个匿名函数,它接收引发的事件,并将事件的两个坐标(即鼠标的坐标)传递给redraw_chart

The redraw_chart function is really dumb: it draws the pie according to the coordinates it received: 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")   

Now, what are redCode , blueCode and whiteCode ? 现在, redCodeblueCodewhiteCode什么? They are the addresses of the three arc objects created by the c.create_arc method. 它们是c.create_arc方法创建的三个弧对象的地址。 They are useful to modify the arcs, so as to avoid creating new ones. 它们对修改弧非常有用,以避免创建新的弧。 There is still one thing left to define: the get_arc function. 还有一件事要定义: get_arc函数。

The get_arc function takes a (x, y) couple, representing a point of the canvas, and returns the corresponding 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

It relies on the is_in_arc function, that takes a point, a portion of the pie, and tells if the point lies in the portion. 它依赖于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

The np.arctan2 function from numpy returns the angle in radians corresponding to the (x, y) point. 来自numpynp.arctan2函数返回对应于(x, y)点的弧度角度。 Then, the fract method returns the corresponding value in degrees. 然后, fract方法以度为单位返回相应的值。 I modified it, because I did not really understand yours: 我修改了它,因为我真的不了解你的:

def frac(n):
    if n < 0:
        n += 2*np.pi
    return 360 * n / (2*np.pi)

So here is what it looks like. 所以这就是它的样子。 You cannot see the cursor one the screenshot, but I guarantee you that the parts turn green when hovered. 您无法在屏幕截图中看到光标,但我保证在悬停时部件会变为绿色。

饼图徘徊

Here is the complete code: 这是完整的代码:

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()

You can use the bind method to, well, bind an event and redraw the chart, like this: 您可以使用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)

See this answer for an example of how to embed the whole thing in a class. 有关如何将整个事物嵌入到类中的示例,请参阅此答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将鼠标悬停在饼图上时如何显示注释并展开楔形? - How to display an annotation and exploding a wedge when hovering over pie chart? 将鼠标悬停在 Plotly 中的饼图上时如何获得标准符号(而不是科学符号) - How to get standard notation (rather than scientific) when hovering over pie chart in Plotly Tkinter 悬停在按钮上-&gt; 颜色变化 - Tkinter Hovering over Button -> Color change 按下鼠标并将鼠标悬停在多个 tkinter 按钮上时,如何更改 state? - How do you change the state of multiple tkinter buttons when your mouse is pressed and hovering over it? 鼠标悬停时如何更改行颜色? Tkinter Treeview - How to change row color when mouse over? Tkinter Treeview 鼠标悬停事件发生时如何更改饼图切片的颜色 - How to change color of pie slice when mouse hover event take place 用Tkinter悬停时更改按钮颜色 - Change button colour when hovering over with tkinter 熊猫时间序列图-将鼠标悬停在线上时显示日期 - Pandas timeseries plot — show date when hovering mouse over the line 在 Python 中用鼠标光标悬停在某物上时显示消息 - Display message when hovering over something with mouse cursor in Python 对于 tkinter 中的多个 PanedWindow,如何在悬停时更改 PanedWindow 的颜色? - how to change the color of PanedWindow upon hovering over it, for multiple PanedWindow in tkinter?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM