6

所以我在 Tkinter 的画布上有一堆文本,我想让它在鼠标悬停在文本上时文本颜色发生变化。对于我的生活,我不知道该怎么做,而且似乎没有很多关于 Tkinter 的信息在任何地方。

for city in Cities:
    CityText = Cities[i]
    board.create_text(CityLocs[CityText][0], CityLocs[CityText][1], text=CityText, fill="white")
    CityText = Cities[i]
    i = i + 1

这只是我将文本放置在画布上的代码,尽管我不确定还要发布什么来表达我的观点。Tkinter 中是否没有“悬停”功能或类似的功能?

4

3 回答 3

5

You can bind arbitrary events (mouse, keyboard, window manager and possibly others) to any widget in Tkinter.

A nice documentation for that is at http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm -

For example, to bind color changes to widgets when mouse hover over them:

import Tkinter
from functools import partial

def color_config(widget, color, event):
    widget.configure(foreground=color)

parent = Tkinter.Tk()
text = Tkinter.Label(parent, text="Hello Text")
text.bind("<Enter>", partial(color_config, text, "red"))
text.bind("<Leave>", partial(color_config, text, "blue"))
text.pack()

Tkinter.mainloop()

The use of functools.partial here allows you to re-use a variable for your text (Label) widget, since you are appending them to a list. If one would settle to simply using lambda you would have a disgusting surprise, as the variable referring to the widget in the body of the lambda function would always point to the last value it had inside the for loop. functools.partial "freeze" the variable content at the time it is called, and yields a new function.

However, since you are placing the items in a Canas, you can either set the "fill" and "fillactive" attributes for each item, as in @mgilson's answer, or you can create a more generic class to handle not only hovering, but other events you choose to implement later.

If your class has a __call__ method, you can pass an instance of it to the bind method of the canvas, so that the resulting object is called for each event on the canvas. In this case, mouse-motion event suffices:

from Tkinter import *

class Follower(object):
    def __init__(self,on_color="#fff", off_color="#000"):
        self.on_color = on_color
        self.off_color = off_color
        self.previous_item = None
    def hover(self, canvas, item, x, y):
        x1, y1, x2, y2 = canvas.bbox(item)
        if x1 <= x <= x2 and y1 <= y <= y2:
            return True
        return False
        
    def __call__(self, event):
        canvas = event.widget
        item = canvas.find_closest(event.x, event.y)
        hovering = self.hover(canvas, item, event.x, event.y)
        if (not hovering or item != self.previous_item) and self.previous_item is not None:
            canvas.itemconfig(self.previous_item, fill=self.off_color)
        if hovering:
            canvas.itemconfig(item, fill=self.on_color)
        self.previous_item = item

master=Tk()
canvas=Canvas(master)
canvas.pack()
canvas.create_text((40,20),text="Hello World!",fill="black")
canvas.create_text((60,80),text="FooBar",fill="black")
canvas.bind("<Motion>", Follower())
master.mainloop()

(ps. canvas and text placement example borrowed from @mgilson's answer)

于 2012-04-20T04:17:00.857 回答
3

这是一个适用于 OS-X 的(不可否认的)相当蹩脚的例子......

from Tkinter import *

master=Tk()
canvas=Canvas(master)
canvas.pack()
canvas.create_text((20,20),activefill="red",text="Hello World!",fill="black")
master.mainloop()

参考: http ://effbot.org/tkinterbook/canvas.htm

于 2012-04-20T03:01:29.880 回答
1

这已经内置在 Tkinter 中。创建文本时使用“activefill”选项来指定您想要的颜色。

有关详细信息,请参阅以下链接。Effbot.org/tkinterbook 是我去 tkinter 的地方。 http://effbot.org/tkinterbook/canvas.htm#Tkinter.Canvas.create_text-method

于 2013-10-22T16:57:14.157 回答