只有第一个 tag_configure 在 treeview widget/tkinter 中的点击事件中被执行
only first tag_configure gets executed on click event within treeview widget/tkinter
过去几个小时我一直坚持这个问题,似乎无法弄清楚为什么代码会这样运行,因此寻求任何帮助。基本上我在 tkinter python 3.6 中有一个 treeview 小部件,其中包含 60000 多个项目。我创建了一个 onTripleClick 函数,'ideally' 应该突出显示具有特定样式(使用标签)的第一个单击项目,并且当下一个项目被三次单击时,先前样式化的项目应该返回到原始状态(使用另一个标签),而新点击的应该呈现样式状态。出于某种原因,只有第一个 tag_configure 被执行 - 如果我注释掉第一个 tag_configure,那么第二个也会被执行 - 我需要它们都在满足 IF 条件时执行第二 tag_configure。非常感谢任何建议!
编辑: 根据要求 - 我已经包含了一个最小版本的工作代码,上面解释的想法是用一种样式(trClicked 标签)突出显示左键单击的行) 并且当另一行被三次单击时,先前单击的项目 returns 回到原始状态(正常标签),而新的项目采用样式(trClicked 标签)。 运行 按原样编写代码,然后注释掉第 9 行的第一个 tree.tag_configure() 位 - 然后重新运行。这次第二个 tree.tag_configure(){line14} 被执行——我需要它们同时执行。谢谢!
from tkinter import *
from tkinter import ttk
def onTripleClick(event):
global selectedSigName, selectedSigPath, trClickedItemiid, toBeClearedItemiid
itemSelection = tree.selection()[0]
trClickedItemiid = tree.focus()
tree.tag_configure('trClicked'+str(trClickedItemiid), background='light green', foreground='black', font=( 'Helvetica' ,8, 'bold', 'italic')) # font=(family, size, weight, slant, underline, overstrike)
# tree.tag_bind('trClicked'+str(trClickedItemiid),'<1>', trClickedItemiid)
prevTrClicked.append(trClickedItemiid)
if len(prevTrClicked) > 1:
toBeClearedItemiid = prevTrClicked.pop(0) # pop the 0th index and pass it to normal
tree.tag_configure('normal'+str(toBeClearedItemiid), background='pink', foreground='black', font=( 'Courier' ,8, 'normal', 'roman'))
# tree.tag_bind('normal'+str(toBeClearedItemiid),'<1>', toBeClearedItemiid)
# Create main root object of TK class
root = Tk()
root.title('MyTreeview')
root.geometry("700x500")
# create frame to house treeview AND scrollbar
frame = Frame(root)
frame.pack(pady=5)
tree = ttk.Treeview(frame, height=20, selectmode="browse")
tree.pack(side=LEFT)
tree['columns'] = ("Column1", "Column2", "Column3")
#Format Columns
tree.column("#0", width=10, minwidth=10) # this is where the plus icon will live
tree.column("Column1", anchor=W, width=150)
tree.column("Column2", anchor=W, width=300)
tree.column("Column3", anchor=W, width=120)
# Create headings
tree.heading("#0", text="", anchor=W)
tree.heading("Column1", text="Column1", anchor=W)
tree.heading("Column2", text="Column2", anchor=W)
tree.heading("Column3", text="Column3", anchor=W)
# to be used by TrClicked Function for helping clear older clicked items
global prevTrClicked
prevTrClicked = [] #
rows= [
['TopMostParent1', '2ndParent-ColE', 'ColF-3rdParent'],
['TopMostParent2', '5thParent-ColE', 'ColF-1stParent'],
['TopMostParent3', '4thParent-ColE', 'ColF-2ndParent'],
['TopMostParent4', '2ndParent-ColE', 'ColF-3rdParent'],
['TopMostParent4', '4thParent-ColE', 'ColF-1stParent'],
['TopMostParent6', '3rdParent-ColE', 'ColF-2ndParent'],
['TopMostParent5', '3rdParent-ColE', 'ColF-1stParent'],
['TopMostParent4', '3rdParent-ColE', 'ColF-3rdParent'],
['TopMostParent2', '3rdParent-ColE', 'ColF-3rdParent']
]
count=0
for row in rows:
tree.insert(parent='', index='end', iid=count, text='', tags=('trClicked'+str(count), 'normal'+str(count)), values=(row[0], row[1], row[2]))
count+=1
tree.bind("<Triple-1>", onTripleClick)
# tree.tag_bind('trClicked'+str(trClickedItemiid),'<1>', trClickedItemiid)
# tree.tag_bind('normal'+str(toBeClearedItemiid),'<1>', toBeClearedItemiid)
root.mainloop()
对于您的情况,列表中标签的顺序很重要
如果我们改变这个
tags=('trClicked'+str(count), 'normal'+str(count))
至此
tags=('normal'+str(count), 'trClicked'+str(count))
这次替换后,之前的元素变成粉红色。
你会看到相反的结果:变成粉红色的元素将不再变成绿色。
解决方案
您为两个标签(背景、前景、字体)使用了相同的样式属性。
在这种情况下,一个 trClicked
标签就足够了。
您只会根据事件更改样式 属性 值。
如果您使用一个标签 ('trClicked'):
tree.tag_configure('trClicked'+str(trClickedItemiid), background='light green', foreground='black', font=( 'Helvetica' ,8, 'bold', 'italic'))
...
tree.tag_configure('trClicked'+str(toBeClearedItemiid), background='pink', foreground='black', font=( 'Courier' ,8, 'normal', 'roman'))
然后,一般来说,一切正常。
完整示例
from tkinter import *
from tkinter import ttk
# to be used by TrClicked Function for helping clear older clicked items
global clicked_queue
clicked_queue = [] # last 3 items
def onTripleClick(event):
global clicked_queue
# 'trClicked'+iid - a unique tag for each item
# the iid (string) of the item that currently has focus, or '' if no item has focus
current_item_iid = event.widget.focus()
if not current_item_iid:
return
print(event.widget.item(current_item_iid))
print("current:", current_item_iid) # iid=count
if clicked_queue:
# get the previous item, the last one in the queue
prev_item_iid = clicked_queue[-1]
print("prev item:", prev_item_iid)
if prev_item_iid == current_item_iid:
return
tree.tag_configure('trClicked'+prev_item_iid, background='pink',
foreground='black', font=( 'Courier' , 8, 'normal', 'roman'))
tree.tag_configure('trClicked'+current_item_iid, background='light green',
foreground='black', font=( 'Helvetica' , 8, 'bold', 'italic'))
# add current item to the right side of the queue
clicked_queue.append(current_item_iid)
print("new prev item:", current_item_iid)
if len(clicked_queue) == 3:
# get and remove an element from the left side of the queue
prev_prev_item_iid = clicked_queue[0]
clicked_queue.remove(prev_prev_item_iid)
if prev_prev_item_iid == current_item_iid:
return
# return to the default style
tree.tag_configure('trClicked'+prev_prev_item_iid, background='white',
foreground='black', font=( 'Courier' , 8, 'normal', 'roman'))
# Create main root object of TK class
root = Tk()
root.title('MyTreeview')
root.geometry("700x500")
# create a consistent style for the background and font
style = ttk.Style()
style.configure('Treeview', background='white', foreground='black', font=( 'Courier' , 8, 'normal', 'roman'))
# create frame to house treeview AND scrollbar
frame = Frame(root)
frame.pack(pady=5)
tree = ttk.Treeview(frame, height=20, selectmode="browse")
tree.pack(side=LEFT)
tree['columns'] = ("Column1", "Column2", "Column3")
#Format Columns
tree.column("#0", width=10, minwidth=10) # this is where the plus icon will live
tree.column("Column1", anchor=W, width=150)
tree.column("Column2", anchor=W, width=300)
tree.column("Column3", anchor=W, width=120)
# Create headings
tree.heading("#0", text="", anchor=W)
tree.heading("Column1", text="Column1", anchor=W)
tree.heading("Column2", text="Column2", anchor=W)
tree.heading("Column3", text="Column3", anchor=W)
rows= [
['TopMostParent1', '2ndParent-ColE', 'ColF-3rdParent'],
['TopMostParent2', '5thParent-ColE', 'ColF-1stParent'],
['TopMostParent3', '4thParent-ColE', 'ColF-2ndParent'],
['TopMostParent4', '2ndParent-ColE', 'ColF-3rdParent'],
['TopMostParent4', '4thParent-ColE', 'ColF-1stParent'],
['TopMostParent6', '3rdParent-ColE', 'ColF-2ndParent'],
['TopMostParent5', '3rdParent-ColE', 'ColF-1stParent'],
['TopMostParent4', '3rdParent-ColE', 'ColF-3rdParent'],
['TopMostParent2', '3rdParent-ColE', 'ColF-3rdParent']
]
count = 1 # <- start at 1 or set iid=str(count), otherwise iid=0 will default to "I001"
for row in rows:
tree.insert(parent='', index='end', iid=count, text='', tags=('trClicked'+str(count),), values=(row[0], row[1], row[2]))
count += 1
tree.bind("<Triple-1>", onTripleClick)
root.mainloop()
过去几个小时我一直坚持这个问题,似乎无法弄清楚为什么代码会这样运行,因此寻求任何帮助。基本上我在 tkinter python 3.6 中有一个 treeview 小部件,其中包含 60000 多个项目。我创建了一个 onTripleClick 函数,'ideally' 应该突出显示具有特定样式(使用标签)的第一个单击项目,并且当下一个项目被三次单击时,先前样式化的项目应该返回到原始状态(使用另一个标签),而新点击的应该呈现样式状态。出于某种原因,只有第一个 tag_configure 被执行 - 如果我注释掉第一个 tag_configure,那么第二个也会被执行 - 我需要它们都在满足 IF 条件时执行第二 tag_configure。非常感谢任何建议!
编辑: 根据要求 - 我已经包含了一个最小版本的工作代码,上面解释的想法是用一种样式(trClicked 标签)突出显示左键单击的行) 并且当另一行被三次单击时,先前单击的项目 returns 回到原始状态(正常标签),而新的项目采用样式(trClicked 标签)。 运行 按原样编写代码,然后注释掉第 9 行的第一个 tree.tag_configure() 位 - 然后重新运行。这次第二个 tree.tag_configure(){line14} 被执行——我需要它们同时执行。谢谢!
from tkinter import *
from tkinter import ttk
def onTripleClick(event):
global selectedSigName, selectedSigPath, trClickedItemiid, toBeClearedItemiid
itemSelection = tree.selection()[0]
trClickedItemiid = tree.focus()
tree.tag_configure('trClicked'+str(trClickedItemiid), background='light green', foreground='black', font=( 'Helvetica' ,8, 'bold', 'italic')) # font=(family, size, weight, slant, underline, overstrike)
# tree.tag_bind('trClicked'+str(trClickedItemiid),'<1>', trClickedItemiid)
prevTrClicked.append(trClickedItemiid)
if len(prevTrClicked) > 1:
toBeClearedItemiid = prevTrClicked.pop(0) # pop the 0th index and pass it to normal
tree.tag_configure('normal'+str(toBeClearedItemiid), background='pink', foreground='black', font=( 'Courier' ,8, 'normal', 'roman'))
# tree.tag_bind('normal'+str(toBeClearedItemiid),'<1>', toBeClearedItemiid)
# Create main root object of TK class
root = Tk()
root.title('MyTreeview')
root.geometry("700x500")
# create frame to house treeview AND scrollbar
frame = Frame(root)
frame.pack(pady=5)
tree = ttk.Treeview(frame, height=20, selectmode="browse")
tree.pack(side=LEFT)
tree['columns'] = ("Column1", "Column2", "Column3")
#Format Columns
tree.column("#0", width=10, minwidth=10) # this is where the plus icon will live
tree.column("Column1", anchor=W, width=150)
tree.column("Column2", anchor=W, width=300)
tree.column("Column3", anchor=W, width=120)
# Create headings
tree.heading("#0", text="", anchor=W)
tree.heading("Column1", text="Column1", anchor=W)
tree.heading("Column2", text="Column2", anchor=W)
tree.heading("Column3", text="Column3", anchor=W)
# to be used by TrClicked Function for helping clear older clicked items
global prevTrClicked
prevTrClicked = [] #
rows= [
['TopMostParent1', '2ndParent-ColE', 'ColF-3rdParent'],
['TopMostParent2', '5thParent-ColE', 'ColF-1stParent'],
['TopMostParent3', '4thParent-ColE', 'ColF-2ndParent'],
['TopMostParent4', '2ndParent-ColE', 'ColF-3rdParent'],
['TopMostParent4', '4thParent-ColE', 'ColF-1stParent'],
['TopMostParent6', '3rdParent-ColE', 'ColF-2ndParent'],
['TopMostParent5', '3rdParent-ColE', 'ColF-1stParent'],
['TopMostParent4', '3rdParent-ColE', 'ColF-3rdParent'],
['TopMostParent2', '3rdParent-ColE', 'ColF-3rdParent']
]
count=0
for row in rows:
tree.insert(parent='', index='end', iid=count, text='', tags=('trClicked'+str(count), 'normal'+str(count)), values=(row[0], row[1], row[2]))
count+=1
tree.bind("<Triple-1>", onTripleClick)
# tree.tag_bind('trClicked'+str(trClickedItemiid),'<1>', trClickedItemiid)
# tree.tag_bind('normal'+str(toBeClearedItemiid),'<1>', toBeClearedItemiid)
root.mainloop()
对于您的情况,列表中标签的顺序很重要
如果我们改变这个
tags=('trClicked'+str(count), 'normal'+str(count))
至此
tags=('normal'+str(count), 'trClicked'+str(count))
这次替换后,之前的元素变成粉红色。 你会看到相反的结果:变成粉红色的元素将不再变成绿色。
解决方案
您为两个标签(背景、前景、字体)使用了相同的样式属性。
在这种情况下,一个 trClicked
标签就足够了。
您只会根据事件更改样式 属性 值。
如果您使用一个标签 ('trClicked'):
tree.tag_configure('trClicked'+str(trClickedItemiid), background='light green', foreground='black', font=( 'Helvetica' ,8, 'bold', 'italic'))
...
tree.tag_configure('trClicked'+str(toBeClearedItemiid), background='pink', foreground='black', font=( 'Courier' ,8, 'normal', 'roman'))
然后,一般来说,一切正常。
完整示例
from tkinter import *
from tkinter import ttk
# to be used by TrClicked Function for helping clear older clicked items
global clicked_queue
clicked_queue = [] # last 3 items
def onTripleClick(event):
global clicked_queue
# 'trClicked'+iid - a unique tag for each item
# the iid (string) of the item that currently has focus, or '' if no item has focus
current_item_iid = event.widget.focus()
if not current_item_iid:
return
print(event.widget.item(current_item_iid))
print("current:", current_item_iid) # iid=count
if clicked_queue:
# get the previous item, the last one in the queue
prev_item_iid = clicked_queue[-1]
print("prev item:", prev_item_iid)
if prev_item_iid == current_item_iid:
return
tree.tag_configure('trClicked'+prev_item_iid, background='pink',
foreground='black', font=( 'Courier' , 8, 'normal', 'roman'))
tree.tag_configure('trClicked'+current_item_iid, background='light green',
foreground='black', font=( 'Helvetica' , 8, 'bold', 'italic'))
# add current item to the right side of the queue
clicked_queue.append(current_item_iid)
print("new prev item:", current_item_iid)
if len(clicked_queue) == 3:
# get and remove an element from the left side of the queue
prev_prev_item_iid = clicked_queue[0]
clicked_queue.remove(prev_prev_item_iid)
if prev_prev_item_iid == current_item_iid:
return
# return to the default style
tree.tag_configure('trClicked'+prev_prev_item_iid, background='white',
foreground='black', font=( 'Courier' , 8, 'normal', 'roman'))
# Create main root object of TK class
root = Tk()
root.title('MyTreeview')
root.geometry("700x500")
# create a consistent style for the background and font
style = ttk.Style()
style.configure('Treeview', background='white', foreground='black', font=( 'Courier' , 8, 'normal', 'roman'))
# create frame to house treeview AND scrollbar
frame = Frame(root)
frame.pack(pady=5)
tree = ttk.Treeview(frame, height=20, selectmode="browse")
tree.pack(side=LEFT)
tree['columns'] = ("Column1", "Column2", "Column3")
#Format Columns
tree.column("#0", width=10, minwidth=10) # this is where the plus icon will live
tree.column("Column1", anchor=W, width=150)
tree.column("Column2", anchor=W, width=300)
tree.column("Column3", anchor=W, width=120)
# Create headings
tree.heading("#0", text="", anchor=W)
tree.heading("Column1", text="Column1", anchor=W)
tree.heading("Column2", text="Column2", anchor=W)
tree.heading("Column3", text="Column3", anchor=W)
rows= [
['TopMostParent1', '2ndParent-ColE', 'ColF-3rdParent'],
['TopMostParent2', '5thParent-ColE', 'ColF-1stParent'],
['TopMostParent3', '4thParent-ColE', 'ColF-2ndParent'],
['TopMostParent4', '2ndParent-ColE', 'ColF-3rdParent'],
['TopMostParent4', '4thParent-ColE', 'ColF-1stParent'],
['TopMostParent6', '3rdParent-ColE', 'ColF-2ndParent'],
['TopMostParent5', '3rdParent-ColE', 'ColF-1stParent'],
['TopMostParent4', '3rdParent-ColE', 'ColF-3rdParent'],
['TopMostParent2', '3rdParent-ColE', 'ColF-3rdParent']
]
count = 1 # <- start at 1 or set iid=str(count), otherwise iid=0 will default to "I001"
for row in rows:
tree.insert(parent='', index='end', iid=count, text='', tags=('trClicked'+str(count),), values=(row[0], row[1], row[2]))
count += 1
tree.bind("<Triple-1>", onTripleClick)
root.mainloop()