2012-04-20 102 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