Home > Net >  How to amend (e.g. add/remove) the values of a ttk.Treeview tag (tkinter)?
How to amend (e.g. add/remove) the values of a ttk.Treeview tag (tkinter)?

Time:11-18

How do I amend (e.g. add/remove) the values of the option tags in a ttk.Treeview? Is there any built in tkinter/widget methods that I can use?

...
columns = list(range(1,3))
tree = ttk.Treeview(root, columns=columns)

tree.insert('', 'end', iid=1, values=(1,1), tags='1')
...
  1. How do I add the value "NEWTAG" to tags='1'? tags should have the values '1' & "NEWTAG".
  2. How do I add the replace '1' with "NEWTAG"? tags value should finally be "NEWTAG".
  3. If the value of tags is already "1' and "NEWTAG", how do I remove "NEWTAG" so that tags="1"?

CodePudding user response:

Treeview takes tupels for the tags and can be added or vise versa like below:

import tkinter as tk
from tkinter import ttk

def add_tag_to_tag(old,new):
    lst = tree.tag_has(old) #returns list of iid's
    for iid in lst:
        old_tags = tree.item(iid)['tags']
        tree.item(iid,tags=(old_tags,new))

root = tk.Tk()
tree = ttk.Treeview(root,columns=())
tree.pack(fill='x')

for i in range(5):
    param = tree['columns'] (f'#{i}',)
    tree.configure(columns=param)
    
for i in range(5):
    tree.heading(column=f'#{i}',text=f'text{i}',anchor='w')
    tree.column(column=f'#{i}', width=150,minwidth=50,stretch=False)

for i in range(5):
    tree.insert('','end',iid=i,values=(i,),tags=(i,),text=str(i))

add_tag_to_tag('1','NEW')
tree.bind('<Button-1>', lambda e:print(tree.item(tree.focus())))

CodePudding user response:

I think what you need is to call some internet tcl widget commands(as mentioned in the comments) that tkinter does not provide. To do this, we use tk.call method. I have created two functions and manually assigned those functions to the Treeview object:

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',)

Though it would be much better to create your own class that does this. Do note that 'OLDTAG' is whatever tag you have given to the items pre-hand. It is not fully foolproof, so feel free to play around.

Entire code without any event driven prooceedures:

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