Python Ttk Treeview: How to Select and Set Focus on a Row

How do I set focus on the first row of a tkinter Treevew list

You set the focus on the widget as a whole with focus_set. To set the tree focus to a specific item you can call the focus method on the treeview, passing it which item you want to have focus.

However, it sounds like you're asking how to set the selection in addition to setting the focus. Just setting the focus alone doesn't change the highlighted state of an item. For that you need to set the selection with selection_set.

To do what you want, you must do the following three things:

  • sets the overall keyboard focus to the tree so that key events are sent to it
  • sets the internal tree focus to the first item, since the tree sends all keyboard events it receives to the focused item
  • sets the selection to the first item so that it is highlighted.

Example:

tree.focus_set()
children = tree.get_children()
if children:
tree.focus(children[0])
tree.selection_set(children[0])

How to set focus to a specific child in a ttk.Treeview similar to clicking on it?

After lots of tries, i've finally managed to figure it out!

With self.dirdisplay being a ttk.Treeview widget...

def c_to_nex(self, event):#Hitting 'Return' on 'c' calls this, setting focus back to 'dirdisplay' treeview, giving focus to child immediately below what was originally clicked.
#Do whatever with data in c
print('Focus acknowledged')
print(self.nextID)#Feedback to show me the nextID actually exists when I hit 'Return'
self.dirdisplay.focus_set()
self.dirdisplay.selection_set((self.nextID, self.nextID))
self.dirdisplay.focus(self.nextID)

You need the trio above to act as if you are programmatically setting focus to a specific child/row in your Treeview - as if the user clicked on it his or herself.

self.dirdisplay.focus_set() gives the Treeview widget input focus so that pressing the up/down keys works properly.

self.dirdisplay.selection_set((self.nextID, self.nextID)) gives you the effect of the row in question actually being highlighted. self.nextID is repeated because selection_set seems to want a list of items (as per the documentation) opposed to a single row/child id.

Finally, self.dirdisplay.focus(self.nextID) seems to be what actually gives the row focus (any functions you have bound to <> will activate).

ttk.Treeview remove row focus color

This can be done with a ttk.Style:

style = ttk.Style(root)
style.map('my.Treeview', background=[], foreground=[])

tree = ttk.Treeview(root, style='my.Treeview', ...)

If instead of removing the selection color, you want to change it:

style.map('my.Treeview', background=[('selected', bgcolor)], 
foreground=[('selected', fgcolor)])

Also, if you loose some other effects after doing this (e.g. the disabled background color), you can look at what was the mapping before you change it:

>>> style.map('Treeview')

{'foreground': [('disabled', '#a3a3a3'), ('selected', '#ffffff')],
'background': [('disabled', '#d9d9d9'), ('selected', '#4a6984')]}

and add back the part about the disabled colors in the mapping list:

style.map('my.Treeview', background=[('disabled', '#d9d9d9')], foreground=[('disabled', '#a3a3a3')])

ttk.Treeview - How to change selection without clicking first

I tried several online examples of Treeview widgets and they all have to have a row clicked before the arrow keys will be able to change the selection. How can this be overriden?

Sadly, the ttk widgets are a bit quirky. You need to make sure the widget as a whole has focus, that an item is selected, and the selected item needs to have the focus. You've done the first two but not the third.

Add the following after calling focus_set():

tree.focus('gallery1')

ttk.treeview selection_set to the item with specific id

You don't need to delete the existing values in order to update the value. You can simply use the set() method to update your treeview.

syntax:

tree.set(iid, column=None, value=None)

If you specify only iid in set method it will return items as dict.

Here is a better way to do the same.

from tkinter import ttk 
import tkinter as tk

titles={'Id': [1,2,3,4,5, 6, 7, 8, 9], 'Names':['Tom', 'Rob', 'Tim', 'Jim', 'Kim', 'Kim', 'Kim', 'Kim', 'Kim']}

def update(selected_index_iid, changed):
index = treev.index(selected_index_iid)# or just index = treev.index(treev.selection())

treev.set(selected_index_iid, 1, changed) # updating the tree
titles['Names'][index] = changed #updating the dictionary
print(titles)

def clicked(event):
global titles
top = tk.Toplevel(window)

label = tk.Label(top, text='Update: ')
label.pack()

entry = tk.Entry(top)
entry.insert(0, treev.set(treev.selection())['1']) #if you only specify the iid 'set' will return dict of items, ['1'] is to select 1st column
entry.pack()

button= tk.Button(top, text='Update', command=lambda :update(treev.selection(), entry.get()))
button.pack()



window = tk.Tk()

treev = ttk.Treeview(window, selectmode ='browse')
treev.bind('<Double-Button-1>', clicked)

treev.pack(side='left',expand=True, fill='both')


verscrlbar = ttk.Scrollbar(window,
orient ="vertical",
command = treev.yview)

verscrlbar.pack(side ='right', fill ='y')
treev.configure(yscrollcommand = verscrlbar.set)

treev["columns"] = list(x for x in range(len(list(titles.keys()))))
treev['show'] = 'headings'


for x, y in enumerate(titles.keys()):
treev.column(x, minwidth=20, stretch=True, anchor='c')
treev.heading(x, text=y)

for args in zip(*list(titles.values())):
treev.insert("", 'end', values =args)

window.mainloop()

python tkinter treeview set focus to newly inserted item

Just define a variable for your tree.insert command.

a = tree.insert(current_node_iid, 1, text="New note")
print (a)

Result:

I001

tkinter Treeview: get selected item values

To get the selected item and all its attributes and values, you can use the item method:

def selectItem(a):
curItem = tree.focus()
print tree.item(curItem)

This will output a dictionary, from which you can then easily retrieve individual values:

{'text': 'Name', 'image': '', 'values': [u'Date', u'Time', u'Loc'], 'open': 0, 'tags': ''}

Also note that the callback will be executed before the focus in the tree changed, i.e. you will get the item that was selected before you clicked the new item. One way to solve this is to use the event type ButtonRelease instead.

tree.bind('<ButtonRelease-1>', selectItem)

Tkinter: Treeview - how to get the index of the selected row after pressing the up/down arrow

You are binding to wrong event, you want to bind to the release of the keys, not to the click of the keys itself:

self.tree.bind('<KeyRelease-Up>', self.tree_key)
self.tree.bind('<KeyRelease-Down>', self.tree_key)


Related Topics



Leave a reply



Submit