I've been stuck on this for the last few hours and can't seem to figure out why the code behaves as it does hence asking for any help. Basically I have a treeview widget in tkinter python 3.6 with 60000+ items. I've created a function onTripleClick that 'ideally' should highlight the first clicked item with certain style (using tags) and WHEN next item is tripleClicked, the previously styled item should go back to original state (using another tag) while the newly clicked should assume the styled state. For some reason ONLY the first tag_configure gets executed - IF i comment out the first tag_configure, then the 2nd one gets executed as well - I need them both to get executed when the IF condition is met for the second tag_configure. Any advice is greatly appreciated!
EDIT: As requested - I've included a minimal version of working code, the idea as explained above is to highlight a triple left clicked row with one style(trClicked tag) and when another row is triple clicked, the previously clicked item returns back to original state(normal tag) while the new one assumes the style(trClicked tag). Run code as is, then comment out the first tree.tag_configure() bit on line 9 - and rerun. This time the 2nd tree.tag_configure(){line14} gets executed -- I need them both to be executed simultaneously. Thank You!
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()
If we change this
tags=('trClicked'+str(count), 'normal'+str(count))
to this
tags=('normal'+str(count), 'trClicked'+str(count))
After this replacement, the previous elements turn pink. You will see the opposite result: the element that turns pink will no longer turn green.
You are using the same style properties for both tags (background, foreground, font).
In this case, a single trClicked
tag is sufficient.
You will only change the style property values based on the event.
If you are using one tag ('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'))
Then, in general, everything works as it should.
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()