Search code examples
pythontkintertreeviewttkttkwidgets

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


I am looking to set focus (highlighted state) of the first row in a tree so that the user only needs to use the arrows to move down or up without having to first select a row. The default should be row 0 highlighted. Here is a sample program as an example. It allows a user to select a row with left-click, then a window will popup with the details of the row.

All suggestions welcome. Thanks

from tkinter import *
from tkinter import ttk
import tkinter as tk


# Display selected row
def msgwindow(xrow):
    curitem = tree.item(tree.focus())
    rowinfo=Toplevel(root) # Child window
    rowinfo.geometry("500x200")  # Size of the window
    rowinfo.title("selected row")
    row_str = tk.StringVar()
    l1 = tk.Label(rowinfo,  textvariable=row_str )
    l1.grid(row=1, column=0)
    row_str.set(curitem['values'][0] + ', ' + curitem['values'][1] + ', ' + curitem['values'][2])
    # Exit selected row window
    def exit_rowinfo(event):
        rowinfo.destroy()

    rowinfo.bind('<Return>', exit_rowinfo)

    # Define exit window button
    rowinfo_back_button = tk.Button(rowinfo, text='Back', padx=20, pady=10, command=lambda: exit_rowinfo(1))
    rowinfo_back_button.grid(row=0, column=1)

# End program
def exit_root(event):
    root.destroy()

tree_columns=('#1', '#2', '#3')

root = Tk()
tree = ttk.Treeview(root, columns=tree_columns, show='headings')
tree.heading('#1', text='First Name')
tree.heading('#2', text='Last Name')
tree.heading('#3', text='Email')
tree.column('#1', width=150)
tree.column('#2', width=150)
tree.column('#3', width=250)

# Define exit window button
tree_exit_button = tk.Button(root, text='Exit', padx=20, pady=10, command=lambda: exit_root(1))
tree_exit_button.grid(row=0, column=6, sticky=N + W)

# generate sample data
def generatetestdata(xtree, xnum):
    contacts = []
    for n in range(1, xnum+1):
        contacts.append((f'first {n}', f'last {n}', f'email{n}@example.com'))
    # adding data to the frame2 tree
    for contact in contacts:
        xtree.insert('', tk.END, values=contact)

generatetestdata(tree, 5)

tree.grid()
tree.bind('<ButtonRelease-1>', msgwindow)
root.bind('<Return>', exit_root)

root.mainloop()


Solution

  • 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])