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
How to Check List Containing Nan
Json.Decoder.Jsondecodeerror: Expecting Value: Line 1 Column 1 (Char 0) Python
How to Read a Specific Line from a Text File in Python
How to Ask a Set of Questions Multiple Times Based on User Input
How to Extract the Substring Between Two Markers
How to Bold Text in Telepot Telegram Bot
How to Remove Text Within Parentheses With a Regex
Python: Read Text File and Split File into List Variables, With Each Variable Having 4 Lines Each
How to Make Python Code to Execute Only Once
Python - Regex Match Multiple Patterns in Multiple Lines
How to Overwrite the Previous Print to Stdout
How to Concatenate/Append Multiple Spark Dataframes Column Wise in Pyspark
How to Execute Local Python Scripts in Jenkins Ui
Make a Batch File Run a Python Code With Arguments
How to Save\Load Models in Spark\Pyspark
How to Make Python Get the Username in Windows and Then Implement It in a Script