2012-04-20 105 views
5

所以我在Tkinter的一个画布上有一大堆文字,我想让文字颜色在鼠标悬停在文字上时发生变化。对于我的生活,我无法弄清楚如何去做,而且在任何地方似乎都没有关于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内置的东西?

+1

您可能希望添加标记和/或将ID存储到您正在创建的文本对象中,以便稍后可以访问它们 – 2012-04-20 02:23:26

回答

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

+0

不错,但只适用于画布对象内的文本元素 - 外部的任意窗口小部件画布没有“填充”或“活动填充”属性。 – jsbueno 2012-04-20 04:18:00

+0

@jsbueno:当然,绑定更通用,正如您已经指出的那样。 (这也是我的第一个想法......),但他问了一个画布上的文本元素,这比绑定任意事件简单得多。另外,您是否可以将事件绑定到由create_text方法生成的item_handle?如果不是,跟踪光标下的文本元素的任务变得更加困难。 – mgilson 2012-04-20 04:26:33

+2

yes you can,'item = canvas.create_text(...); canvas.tag_bind(item,“”,callback)'。此外,正如Joel的评论所建议的那样,您可以为所有相应的项目create_text(...,tag =“city_name”)添加一个标签,然后对该标签执行绑定。 – FabienAndre 2012-04-20 13:26:23

2

可以绑定任意事件(鼠标,键盘,窗口管理器和其它可能的)到Tkinter中的任何小部件。

为一个不错的文件是在http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm -

例如,结合颜色变为小部件时,鼠标悬停在他们:

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

采用functools.partial在这里,您可以重新使用您的文本(标签)小部件的变量,因为您将它们附加到列表中。如果你愿意简单地使用lambda表达式,那么你会有一个令人厌恶的惊喜,因为引用lambda函数主体中的部件的变量总是指向它在for循环内的最后一个值。 functools.partial在被调用时“冻结”变量内容,并产生一个新函数。

但是,由于您将项目放置在Canas中,因此您可以为每个项目设置“fill”和“fillactive”属性,如@ mgilson的答案,或者可以创建更通用的类来处理不只有悬停,但您选择稍后执行的其他事件。

如果您的课程有__call__方法,您可以将其实例传递给画布的bind方法,以便为画布上的每个事件调用结果对象。在这种情况下,鼠标移动事件足以:(PS。从@ mgilson的回答借来的画布和文本放置示例)

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

+0

如果'pack'或'grid'几何管理器足够用于文本放置,那么这是一个很好的答案...我想'place'几何管理器也可以使用...但这很难看得很快,我认为... – mgilson 2012-04-20 04:29:07

+0

@mgilson:的确 - OP确实需要Canvas - 这个新例子应该以更通用的方式来覆盖它。 (当我第一次写答案的时候,我认为一个文化可以把事件绑定到画布上,但实际上你需要一些事件管理器来将事件重新分配给像这里第二个例子中的类) – jsbueno 2012-04-20 04:49:22

+0

我没有测试它,但它看起来很稳固。我的一个保留是,它看起来像你的班级将*总是*选择一个项目用on_color着色(只要光标在画布上)。如果标签足够稀疏,以至于有时会希望它们中的任何一个都不活动(例如,如果光标不够近),或者光标离开(尽管这可能是一个更简单的修复,将previous_item的颜色设置为off_color,并在绑定到“”的方法中将其设置为None。 – mgilson 2012-04-20 05:03:21