如何修改(例如 add/remove)ttk.Treeview 标签(tkinter)的值?
How to amend (e.g. add/remove) the values of a ttk.Treeview tag (tkinter)?
如何修改(例如 add/remove)ttk.Treeview
中选项 tags
的值?有没有我可以使用的内置 tkinter/widget 方法?
...
columns = list(range(1,3))
tree = ttk.Treeview(root, columns=columns)
tree.insert('', 'end', iid=1, values=(1,1), tags='1')
...
- 如何将值“NEWTAG”添加到
tags='1'
? tags
应具有值“1”和“NEWTAG”。
- 如何添加用“NEWTAG”替换“1”?
tags
值最终应该是“NEWTAG”。
- 如果
tags
的值已经是“1”和“NEWTAG”,如何删除“NEWTAG”以便 tags="1"?
我认为您需要调用一些 tkinter
未提供的 internet tcl widget 命令(如评论中所述)。为此,我们使用 tk.call
方法。我创建了两个函数并手动将这些函数分配给 Treeview
对象:
def add_tag(new_tag,iid):
root.tk.call(tree,'tag','add',new_tag,iid)
def replace_tag(new_tag,to_be_replaced,iid=''):
"""If iid is ommited, replaces the old_tag from all the items if it exists"""
if iid:
root.tk.call(tree,'tag','add',new_tag,iid)
root.tk.call(tree,'tag','remove',to_be_replaced,iid)
else:
iids = tree.tag_has(to_be_replaced)
root.tk.call(tree,'tag','remove',to_be_replaced)
for i in iids:
root.tk.call(tree,'tag','add',new_tag,i)
def delete_tag(tag_to_delete,iid=''):
"""If iid is ommited, deletes all the tag from all items"""
if iid:
root.tk.call(tree,'tag','remove',tag_to_delete,iid)
else:
root.tk.call(tree,'tag','remove',tag_to_delete)
tree.add_tag = add_tag
tree.replace_tag = replace_tag
tree.delete_tag = delete_tag
iids = tree.tag_has('OLDTAG')
# Adding a tag to the first item in the treeview
tree.add_tag('NEWTAG',iids[0]) # Choosing the first item
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('OLDTAG', 'NEWTAG')
# Replacing the OLDTAG for all items
tree.replace_tag('OLDEST','OLDTAG')
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('NEWTAG', 'OLDEST')
# Delete NEWTAG for the first item
tree.delete_tag('NEWTAG',iids[0])
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('OLDEST',)
虽然创建自己的 class 会更好。请注意,'OLDTAG' 是您预先给物品的任何标签。并非万无一失,请随意尝试。
没有任何事件驱动程序的完整代码:
from tkinter import *
from tkinter import ttk
root = Tk()
tree = ttk.Treeview(root,columns=('No.','Name'),show='headings')
tree.pack()
def add_tag(new_tag,iid):
root.tk.call(tree,'tag','add',new_tag,iid)
def replace_tag(new_tag,to_be_replaced,iid=''):
"""If iid is not specified replaces the old_tag from all the items if it exists"""
if iid:
root.tk.call(tree,'tag','add',new_tag,iid)
root.tk.call(tree,'tag','remove',to_be_replaced,iid)
else:
iids = tree.tag_has(to_be_replaced)
root.tk.call(tree,'tag','remove',to_be_replaced)
for i in iids:
root.tk.call(tree,'tag','add',new_tag,i)
def delete_tag(tag_to_delete,iid=''):
"""If iid is ommited, deletes all the tag from all items"""
if iid:
root.tk.call(tree,'tag','remove',tag_to_delete,iid)
else:
root.tk.call(tree,'tag','remove',tag_to_delete)
lst = [[1,'Me'],[2,'Myself'],[3,'I']]
for i in ('No.','Name'):
tree.heading(i,text=i)
tree.column(i,width=100)
for i in lst:
tree.insert('','end',values=i,tags='OLDTAG')
iids = tree.tag_has('OLDTAG')
tree.add_tag = add_tag
tree.replace_tag = replace_tag
tree.delete_tag = delete_tag
# Adding a tag to the first item in the treeview
tree.add_tag('NEWTAG',iids[0]) # Choosing the first item
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('OLDTAG', 'NEWTAG')
# Replacing the OLDTAG for all items
tree.replace_tag('OLDEST','OLDTAG')
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('NEWTAG', 'OLDEST')
# Delete NEWTAG for the first item
tree.delete_tag('NEWTAG',iids[0])
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('OLDEST',)
root.mainloop()
根据 tcl documentation,ttk.Treeview
小部件确实具有向节点或节点列表添加和删除标签的命令。但是,官方的 tkinter 包装器中没有提供这些方法;请参阅 /usr/lib/python3.8/tkinter/ttk.py.
中的 Treeview
class
基于@JasonYang 的评论和@CoolCloud 的回答,下面的测试代码说明了如何实现包装器来访问 ttk.Treeview
的 tag add
和 tag remove
命令小部件。希望这个例子可以让tkinter用户受益。
测试代码:请参阅# Methods to add and remove tag(s)
部分。有关为什么使用小部件的 ._w
属性的解释,请阅读 。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import tkinter as tk
import tkinter.ttk as ttk
class App(ttk.Frame):
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent)
self.parent = parent
self._create_treeview()
self._test_tag_add_method()
self._test_tag_remove_method()
def _create_treeview(self):
# Create Treeview
self.tree = ttk.Treeview(self, column=('A', 'B'), selectmode='none',
height=7)
self.tree.grid(row=0, column=0, sticky='nsew')
# Setup column heading
self.tree.heading('#0', text='Point', anchor='center')
self.tree.heading('#1', text='x', anchor='center')
self.tree.heading('#2', text='y', anchor='center')
# #0, #01, #02 denotes the 0, 1st, 2nd columns
# Setup column
self.tree.column('#0', anchor='center', width=50)
self.tree.column('#1', anchor='center', width=30)
self.tree.column('#2', anchor='center', width=30)
# Insert nodes
data = [(10, 20), (30, 40), (50, 60)]
for n, d in enumerate(data):
self.tree.insert('', 'end', iid='n'+str(n), text=str(n), value=d,
tag='Current')
node = 'n5 xxx'
self.tree.insert('', 'end', iid=node, text=node, value=d, tag='Current')
print(f"Nodes with 'Current' tag: {self.tree.tag_has('Current')}")
def _test_tag_add_method(self):
# Add 'House' to tag of node 'n1'
tag = 'House'
self.tag_add(tag, items='n1') # works but incorrect type for items
print(f"Nodes with 'House' tag: {self.tree.tag_has(tag)}")
self.tag_add(tag, items=['n5 xxx']) # Correct way of submitting items
print(f"Nodes with 'House' tag: {self.tree.tag_has(tag)}")
# Add 'NEWTAG' to tag of all nodes
tag = 'NEWTAG'
self.tag_add(tag, items=self.tree.get_children())
print(f"Nodes with 'NEWTAG' tag: {self.tree.tag_has(tag)}")
def _test_tag_remove_method(self):
# Remove 'House' to tag of node 'n1'
tag = 'House'
self.tag_remove(tag, items='n1') # works but incorrect type for items
print(f"Nodes with 'House' tag: {self.tree.tag_has(tag)}")
self.tag_remove(tag, items=['n5 xxx']) # Correct way of submitting items
print(f"Nodes with 'House' tag: {self.tree.tag_has(tag)}")
# Add 'NEWTAG' to tag of all nodes
tag = 'NEWTAG'
self.tag_remove(tag, items=self.tree.get_children())
print(f"Nodes with 'NEWTAG' tag: {self.tree.tag_has(tag)}")
###########################################################################
# Methods to add and remove tag(s)
###########################################################################
def tag_add(self, tag, items=None):
'''Adds the specified tag to each of the listed items. If tag is
already present for a particular item, then the tags for that item are
unchanged. Note: items refers to the iid of the tree nodes and must be
a list object.
'''
if items is None:
self.tk.call(self.tree._w, 'tag', 'add', tag)
else:
self.tk.call(self.tree._w, 'tag', 'add', tag, items)
def tag_remove(self, tag, items=None):
'''Removes the specified tag from each of the listed items. If items is
omitted, removes tag from each item in the tree. If tag is not present
for a particular item, then the tags for that item are unchanged.
Note: items refers to the iid of the tree nodes and must be a list
object.
'''
if items is None:
self.tk.call(self.tree._w, 'tag', 'remove', tag)
else:
self.tk.call(self.tree._w, 'tag', 'remove', tag, items)
###########################################################################
if __name__ == '__main__':
root = tk.Tk()
app = App(root)
app.grid(row=0, column=0, sticky='nsew')
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.mainloop()
备注:在tag add
和tag remove
方法中,items
参数必须是列表对象,不能是字符串对象。 items
参数的元素必须是字符串对象。如果将带有白色 space 的字符串对象作为 items
传入,则会出现 。
如何修改(例如 add/remove)ttk.Treeview
中选项 tags
的值?有没有我可以使用的内置 tkinter/widget 方法?
...
columns = list(range(1,3))
tree = ttk.Treeview(root, columns=columns)
tree.insert('', 'end', iid=1, values=(1,1), tags='1')
...
- 如何将值“NEWTAG”添加到
tags='1'
?tags
应具有值“1”和“NEWTAG”。 - 如何添加用“NEWTAG”替换“1”?
tags
值最终应该是“NEWTAG”。 - 如果
tags
的值已经是“1”和“NEWTAG”,如何删除“NEWTAG”以便tags="1"?
我认为您需要调用一些 tkinter
未提供的 internet tcl widget 命令(如评论中所述)。为此,我们使用 tk.call
方法。我创建了两个函数并手动将这些函数分配给 Treeview
对象:
def add_tag(new_tag,iid):
root.tk.call(tree,'tag','add',new_tag,iid)
def replace_tag(new_tag,to_be_replaced,iid=''):
"""If iid is ommited, replaces the old_tag from all the items if it exists"""
if iid:
root.tk.call(tree,'tag','add',new_tag,iid)
root.tk.call(tree,'tag','remove',to_be_replaced,iid)
else:
iids = tree.tag_has(to_be_replaced)
root.tk.call(tree,'tag','remove',to_be_replaced)
for i in iids:
root.tk.call(tree,'tag','add',new_tag,i)
def delete_tag(tag_to_delete,iid=''):
"""If iid is ommited, deletes all the tag from all items"""
if iid:
root.tk.call(tree,'tag','remove',tag_to_delete,iid)
else:
root.tk.call(tree,'tag','remove',tag_to_delete)
tree.add_tag = add_tag
tree.replace_tag = replace_tag
tree.delete_tag = delete_tag
iids = tree.tag_has('OLDTAG')
# Adding a tag to the first item in the treeview
tree.add_tag('NEWTAG',iids[0]) # Choosing the first item
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('OLDTAG', 'NEWTAG')
# Replacing the OLDTAG for all items
tree.replace_tag('OLDEST','OLDTAG')
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('NEWTAG', 'OLDEST')
# Delete NEWTAG for the first item
tree.delete_tag('NEWTAG',iids[0])
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('OLDEST',)
虽然创建自己的 class 会更好。请注意,'OLDTAG' 是您预先给物品的任何标签。并非万无一失,请随意尝试。
没有任何事件驱动程序的完整代码:
from tkinter import *
from tkinter import ttk
root = Tk()
tree = ttk.Treeview(root,columns=('No.','Name'),show='headings')
tree.pack()
def add_tag(new_tag,iid):
root.tk.call(tree,'tag','add',new_tag,iid)
def replace_tag(new_tag,to_be_replaced,iid=''):
"""If iid is not specified replaces the old_tag from all the items if it exists"""
if iid:
root.tk.call(tree,'tag','add',new_tag,iid)
root.tk.call(tree,'tag','remove',to_be_replaced,iid)
else:
iids = tree.tag_has(to_be_replaced)
root.tk.call(tree,'tag','remove',to_be_replaced)
for i in iids:
root.tk.call(tree,'tag','add',new_tag,i)
def delete_tag(tag_to_delete,iid=''):
"""If iid is ommited, deletes all the tag from all items"""
if iid:
root.tk.call(tree,'tag','remove',tag_to_delete,iid)
else:
root.tk.call(tree,'tag','remove',tag_to_delete)
lst = [[1,'Me'],[2,'Myself'],[3,'I']]
for i in ('No.','Name'):
tree.heading(i,text=i)
tree.column(i,width=100)
for i in lst:
tree.insert('','end',values=i,tags='OLDTAG')
iids = tree.tag_has('OLDTAG')
tree.add_tag = add_tag
tree.replace_tag = replace_tag
tree.delete_tag = delete_tag
# Adding a tag to the first item in the treeview
tree.add_tag('NEWTAG',iids[0]) # Choosing the first item
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('OLDTAG', 'NEWTAG')
# Replacing the OLDTAG for all items
tree.replace_tag('OLDEST','OLDTAG')
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('NEWTAG', 'OLDEST')
# Delete NEWTAG for the first item
tree.delete_tag('NEWTAG',iids[0])
all_tags = tree.item(iids[0],'tags')
print(f'All tag for the given iid: {all_tags}') # ('OLDEST',)
root.mainloop()
根据 tcl documentation,ttk.Treeview
小部件确实具有向节点或节点列表添加和删除标签的命令。但是,官方的 tkinter 包装器中没有提供这些方法;请参阅 /usr/lib/python3.8/tkinter/ttk.py.
Treeview
class
基于@JasonYang 的评论和@CoolCloud 的回答,下面的测试代码说明了如何实现包装器来访问 ttk.Treeview
的 tag add
和 tag remove
命令小部件。希望这个例子可以让tkinter用户受益。
测试代码:请参阅# Methods to add and remove tag(s)
部分。有关为什么使用小部件的 ._w
属性的解释,请阅读
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import tkinter as tk
import tkinter.ttk as ttk
class App(ttk.Frame):
def __init__(self, parent=None, *args, **kwargs):
super().__init__(parent)
self.parent = parent
self._create_treeview()
self._test_tag_add_method()
self._test_tag_remove_method()
def _create_treeview(self):
# Create Treeview
self.tree = ttk.Treeview(self, column=('A', 'B'), selectmode='none',
height=7)
self.tree.grid(row=0, column=0, sticky='nsew')
# Setup column heading
self.tree.heading('#0', text='Point', anchor='center')
self.tree.heading('#1', text='x', anchor='center')
self.tree.heading('#2', text='y', anchor='center')
# #0, #01, #02 denotes the 0, 1st, 2nd columns
# Setup column
self.tree.column('#0', anchor='center', width=50)
self.tree.column('#1', anchor='center', width=30)
self.tree.column('#2', anchor='center', width=30)
# Insert nodes
data = [(10, 20), (30, 40), (50, 60)]
for n, d in enumerate(data):
self.tree.insert('', 'end', iid='n'+str(n), text=str(n), value=d,
tag='Current')
node = 'n5 xxx'
self.tree.insert('', 'end', iid=node, text=node, value=d, tag='Current')
print(f"Nodes with 'Current' tag: {self.tree.tag_has('Current')}")
def _test_tag_add_method(self):
# Add 'House' to tag of node 'n1'
tag = 'House'
self.tag_add(tag, items='n1') # works but incorrect type for items
print(f"Nodes with 'House' tag: {self.tree.tag_has(tag)}")
self.tag_add(tag, items=['n5 xxx']) # Correct way of submitting items
print(f"Nodes with 'House' tag: {self.tree.tag_has(tag)}")
# Add 'NEWTAG' to tag of all nodes
tag = 'NEWTAG'
self.tag_add(tag, items=self.tree.get_children())
print(f"Nodes with 'NEWTAG' tag: {self.tree.tag_has(tag)}")
def _test_tag_remove_method(self):
# Remove 'House' to tag of node 'n1'
tag = 'House'
self.tag_remove(tag, items='n1') # works but incorrect type for items
print(f"Nodes with 'House' tag: {self.tree.tag_has(tag)}")
self.tag_remove(tag, items=['n5 xxx']) # Correct way of submitting items
print(f"Nodes with 'House' tag: {self.tree.tag_has(tag)}")
# Add 'NEWTAG' to tag of all nodes
tag = 'NEWTAG'
self.tag_remove(tag, items=self.tree.get_children())
print(f"Nodes with 'NEWTAG' tag: {self.tree.tag_has(tag)}")
###########################################################################
# Methods to add and remove tag(s)
###########################################################################
def tag_add(self, tag, items=None):
'''Adds the specified tag to each of the listed items. If tag is
already present for a particular item, then the tags for that item are
unchanged. Note: items refers to the iid of the tree nodes and must be
a list object.
'''
if items is None:
self.tk.call(self.tree._w, 'tag', 'add', tag)
else:
self.tk.call(self.tree._w, 'tag', 'add', tag, items)
def tag_remove(self, tag, items=None):
'''Removes the specified tag from each of the listed items. If items is
omitted, removes tag from each item in the tree. If tag is not present
for a particular item, then the tags for that item are unchanged.
Note: items refers to the iid of the tree nodes and must be a list
object.
'''
if items is None:
self.tk.call(self.tree._w, 'tag', 'remove', tag)
else:
self.tk.call(self.tree._w, 'tag', 'remove', tag, items)
###########################################################################
if __name__ == '__main__':
root = tk.Tk()
app = App(root)
app.grid(row=0, column=0, sticky='nsew')
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.mainloop()
备注:在tag add
和tag remove
方法中,items
参数必须是列表对象,不能是字符串对象。 items
参数的元素必须是字符串对象。如果将带有白色 space 的字符串对象作为 items
传入,则会出现