简体   繁体   中英

Ttk Treeview: track keyboard selection

Here is a Tk widget with a ttk treeview. When user clicks on the row, some function is executed (here it just prints item text). What I need is the following:

  1. Initially a focus is on the text entry. When user presses Tab key, the focus should go to the first row, and the function bound to Click event should be executed.
  2. When user goes up and down in a treeview using the keyboard, this function should be executed as well, once a next cell is selected.

I can't find anything related to these questions. Is ttk treeview capable to track keyboard? Thanks.

import tkinter as tk
import tkinter.ttk as ttk

class App(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.CreateUI()
        self.grid(sticky = (tk.N,tk.S,tk.W,tk.E))
        parent.grid_rowconfigure(0, weight = 1)
        parent.grid_columnconfigure(0, weight = 1)

    def CreateUI(self):
        tv = ttk.Treeview(self,yscrollcommand=sc.set,height=30)
        tv['columns'] = ('Name',)
        tv.heading("#0", text='Items')
        tv.column("#0", anchor="w",width=75)
        tv.heading('Name', text='Name')
        tv.column('Name', anchor='w', width=150)
        tv.grid(sticky = (tk.N,tk.S,tk.W,tk.E))
        self.treeview = tv
        self.treeview.bind('<1>',self.OnClick)

    def OnClick(self,event):
        rowid=self.treeview.identify_row(event.y)
        self.treeview.selection_set(rowid)
        it=self.treeview.selection()[0]
        print(self.treeview.item(it,'values')[0])

items=[]
for i in range(100):
    items.append([i,'Item %d' % i])

root=tk.Tk()
sv=tk.StringVar()
filt=tk.Entry(root,textvariable=sv)
filt.grid(row=0,column=0,sticky='nw')
sc=tk.Scrollbar(root)
sc.grid(row=1,column=1,sticky='ns')
item_list=App(root)
item_list.grid(row=1,column=0,sticky='ns')
sc.config(command=item_list.treeview.yview)
for i in range(len(items)):
    item_list.treeview.insert('', 'end', iid=str(i), text=items[i][0], values=(items[i][1],))
item_list.treeview.selection_set('0')

def update_filter(*args):
    global items,item_list,sv
    filtr=sv.get().lower()
    item_list.treeview.delete(*(item_list.treeview).get_children())
    for i in range(len(items)):
        if filtr in str(items[i][0]).lower() or filtr in str(items[i][1]).lower():
            item_list.treeview.insert('', 'end', iid=str(i), text=items[i][0], values=(items[i][1],))
    item_list.treeview.update()
    item_list.update()

sv.trace('w', update_filter)
filt.focus()
root.mainloop()

As I read from the comments, you need some function to extract the current selection (or a part of that) from your treeview, execute a trigger action for another treeview on the selection.

Therefore you can perfectly use the virtual <<TreeviewSelect>> -Event @CommonSense suggested.

As per documentation :

45.1. Virtual events for the ttk.Treeview widget

Certain state changes within a Treeview widget generate virtual events that you can use to respond to these changes; see Section 54.8, “Virtual events”.

  • Whenever there is a change in the selection, either by items becoming selected or becoming unselected, the widget generates a “<&ltTreeviewSelect>>” event.
  • Whenever an item is opened, the widget generates a “<&ltTreeviewOpen>>” event.
  • Whenever an item is closed, the widget generates a “<&ltTreeviewClose>>” event.

Then use ttk.treeview.focus() to get the currently selected iid . ttk.treeview.item(ttk.treeview.focus()) will give you the item you need to operate on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM