Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
888 views
in Technique[技术] by (71.8m points)

python - ttk.treeview selection_set to the item with specific id

I want to edit an item in treeview by another Toplevel window and after editing want to refresh / reload items into list from database and set focus to the edited item. The problem I am facing is to SET FOCUS TO THE EDITED ITEM IN TREEVIEW. Any help will be appreciated. Here is the minimal sample code.

    import tkinter as tk
    from tkinter import ttk

    class _tree(tk.Frame):
        def __init__(self, *args):
            tk.Frame.__init__(self, *args)
            self.tree = ttk.Treeview(self, columns = ("id", "name"))
            self.tree.heading("#0", text = "s.n")
            self.tree.heading("#1", text = "id")
            self.tree.heading("#2", text = "name")
            self.tree.pack()
            _items = [[52,"orange"],[61,"manggo"],[1437,"apple"]] # item with id 61 needs to be changed
            sn = 1
            for r in (_items):
                self.tree.insert("", "end", text = str(sn), values = (r[0], r[1]))
                sn += 1
            self.tree.bind("<Double-Button-1>", self._item)

        def _item(self, event):
            global item_values
            global item_id
            global item_name
            idx = self.tree.selection()
            item_values = self.tree.item(idx)
            print("item_values : %s" % item_values)
            item_id = self.tree.set(idx, "#1")
            item_name = self.tree.set(idx, "#2")
            edit_item(self)
    class edit_item(tk.Toplevel):
        def __init__(self, master, *args):
            tk.Toplevel.__init__(self, master)
            self.master = master
            global item_values
            global item_name
            lbl1 = tk.Label(self, text = "item name")
            self.ent1 = tk.Entry(self)
            btn1 = tk.Button(self, text = "update", command = self.update_item)
            lbl1.place(x=0, y=10)
            self.ent1.place(x=90, y=10)
            btn1.place(x=90, y=100)
            self.ent1.insert(0, item_name)
        def update_item(self):
            for i in self.master.tree.get_children():
                self.master.tree.delete(i)
            new_data = [[52,"orange"],[61,"mango"],[1437,"apple"]] # item with id 61 has been changed
            sn = 1
            for r in (new_data):
                self.master.tree.insert("", "end", text = str(sn), values = (r[0], r[1]))
                sn += 1
            # Need to set focus on item with id 61 
            idx = self.master.tree.get_children(item_values['values'][0]) # HERE  NEED  HELP
            self.master.tree.focus_set()
            self.master.tree.selection_set(idx)
            self.master.tree.focus(idx)
            self.destroy()
    def main():
        root = tk.Tk()
        app = _tree()
        app.pack()
        root.mainloop()
if __name__ == "__main__":
    main()

`

I am receiving the following error:
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
    return self.func(*args)
  File "test_tree.py", line 55, in update_item
    idx = self.master.tree.get_children(item_values['values'][0]) # HERE  NEED  HELP
  File "/usr/lib/python3.8/tkinter/ttk.py", line 1225, in get_children
    self.tk.call(self._w, "children", item or '') or ())
_tkinter.TclError: Item 61 not found


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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() 


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...