鼠标悬停时如何更改行颜色? Tkinter 树视图

问题描述

我最近一直在使用 Tkinter ttk.Treeview 小部件,我已经能够使用 ttk.Style 更改很多小部件的样式,但遗憾的是我无法找到解决此问题的方法:>

如何在光标/鼠标结束时更改项目的颜色?

就像 activebackgroundTkinter.Button 选项。 与 VS CODE 树状视图类似:当您在浏览器中导航时,光标下的文件/文件夹会更改背景颜色。

解决方法

这是一个例子。您可以进一步改进此代码。

import tkinter as tk
from tkinter import ttk


def Enter_event(event):

    for x in tree.get_children():
        tree.tag_configure(tree.item(x)['tags'],background='')

    tree.tag_configure(tree.item(tree.identify_row(event.y))['tags'],background='yellow')

root = tk.Tk()
style = ttk.Style() 
  
  
style.configure('W.TButton') 

tree = ttk.Treeview(root,style = 'W.TButton')

tree.pack()
for i in range(10):
    tree.insert("","end",text="Item %s" % i,tags=i)
    tree.tag_bind(i,'<Motion>',Enter_event)
        
root.mainloop()

说明:

使用为每个单元格设置一个标签,然后将每个标签绑定到运动事件并调用事件处理程序。

  • tree.item(x)['tags'] 返回指定 iid 的标签。

  • tree.get_children() 返回所有孩子的 iid

  • tree.identify_row(event.y) 返回 y 位置的行。

  • tree.tag_configure(tree.item(tree.identify_row(event.y))['tags'],background='yellow') 将改变指定标签的背景。

我尝试了 Enter 和 leave 事件,但没有被识别。 (另外,请注意将样式配置为“Treeview”对我不起作用。如果对任何读者有用,请通知我)

,

你可以用标签来控制一行的颜色,所以解决方案的第一部分是定义一个标签来突出一行:

tree.tag_configure('highlight',background='lightblue')

接下来,编写一个方法,该方法将从树中的所有项目中删除该标签,然后将其添加到光标下的项目中。底层 tk 小部件具有添加和删除标签的方法,但这些方法未公开,因此我们需要直接调用底层 tk 代码。

def highlight_row(event):
    tree = event.widget
    item = tree.identify_row(event.y)
    tree.tk.call(tree,"tag","remove","highlight")
    tree.tk.call(tree,"add","highlight",item)

最后,将函数绑定到 <Motion> 事件:

tree.bind("<Motion>",highlight_row)

这是一个完整的工作示例:

import tkinter as tk
from tkinter import ttk


def highlight_row(event):
    tree = event.widget
    item = tree.identify_row(event.y)
    tree.tk.call(tree,item)

root = tk.Tk()

tree = ttk.Treeview(root,style = 'W.TButton')
vsb = ttk.Scrollbar(root,command=tree.yview)
tree.configure(yscrollcommand=vsb.set)

vsb.pack(side="right",fill="y")
tree.pack(side="left",fill="both",expand=True)

tree.tag_configure('highlight',background='lightblue')
tree.bind("<Motion>",highlight_row)


for i in range(100):
    tree.insert("",text=f"Item #{i+1}")
    tree.tag_bind(i,highlight_row)

root.mainloop()

screenshot