menu

Questions & Answers

Update item selected from treeview in tkinter

I have a json that shows me its contents in a treeview. I currently have a function that selects the item and displays it in boxes for editing. My question is how to call the json in this function so that the update shown in the treeview is updated in the json.

this function updates the item in the treeview

def update_record():        
    selected = json_tree.focus()
    json_tree.item(selected, text='', values=(str(logo_lb.get()),str(name_lb.get()),str(lastname_lb.get()),str(something_lb.get())))

I tried this way and it modifies the item in the treeview but in the json it adds the data instead of replacing it.

selected = json_tree.focus()
    json_tree.item(selected, text='', values=(str(logo_lb.get()),str(name_lb.get()),str(lastname_lb.get()),str(something_lb.get())))
    with open('prueba1.json', "r") as f:
        data = json.load(f)
        temp = data["Example"]
        y = {
                    "Logo": str(logo_lb.get()),
                    "Name": str(name_lb.get()),
                    "Last Name": str(lastname_lb.get()),
                    "Something": str(something_lb.get()),
                    
                    }
        temp.append(y)

    with open('prueba1.json', 'w') as f:
        json.dump(data, f, indent=4)

This is a example of how it works

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

ventana = tk.Tk()
ventana.title("Test")
ventana.geometry("1000x600")

frame1 = tk.Frame(ventana, bg="green", height=300, width=700)
frame1.grid(row=1, column=0)

frame2 = tk.Frame(ventana, bg="yellow", height=300, width=700)
frame2.grid(row=2, column=0)

frame_entry = tk.Frame(frame2) 
frame_entry.pack(pady=20)

tree_frame = tk.Frame(frame1) 
tree_frame.pack(pady=20)

#style del tree
style = ttk.Style()
style.theme_use("clam")
style.configure("Treeview", background="#c7c7c7", foreground="black", rowheight=25,fieldbackground="#a1a1a1")
style.map("Treeview", background=[('selected','green')])

tree_scroll = Scrollbar(tree_frame) #Frame para el scrollbar del arbol
tree_scroll.pack(side=RIGHT, fill=Y)
#Lista Treeview
json_tree = ttk.Treeview(tree_frame, yscrollcommand=tree_scroll.set)
json_tree.pack()

#config scroll
tree_scroll.config(command=json_tree.yview)

json_tree['column'] = ("Logo", "Name", "Last Name", "Something")

json_tree.column("#0", width=0, minwidth=0)
json_tree.column("Logo", anchor="w", width=120)
json_tree.column("Name", anchor="w", width=120)
json_tree.column("Last Name", anchor="w", width=120)
json_tree.column("Something", anchor="w", width=120)

#headings
json_tree.heading("#0", text="", anchor="w")
json_tree.heading("Logo", text="Logo", anchor="w")
json_tree.heading("Name", text="Name", anchor="w")
json_tree.heading("Last Name", text="Last Name", anchor="w")
json_tree.heading("Something", text="Something", anchor="w")

#color rows
json_tree.tag_configure('par', background="#fff")
json_tree.tag_configure('inpar', background="#d6d6d6")

#Open and read json

with open('prueba1.json', "r") as f:
    data = json.load(f)


    count=0
    for record in data['Example']:
        if count % 2 ==0:
            json_tree.insert(parent='', index="end", iid=count, text="", values=(record['Logo'],record['Name'],record['Last Name'],record['Something']), tags=('par',))
        else:    
            json_tree.insert(parent='', index="end", iid=count, text="", values=(record['Logo'],record['Name'],record['Last Name'],record['Something']), tags=('inpar',))

        count+=1


#entrys
l1 = Label( frame_entry, text="Logo")
l1.grid(row=0, column=0)
logo_lb = Entry( frame_entry)
logo_lb.grid(row=1, column=0)

l2 = Label( frame_entry, text="Name")
l2.grid(row=0, column=1)
name_lb = Entry(frame_entry)
name_lb.grid(row=1, column=1)

l3 = Label( frame_entry, text="Last Name")
l3.grid(row=0, column=2)
lastname_lb = Entry(frame_entry)
lastname_lb.grid(row=1, column=2)

l4 = Label( frame_entry, text="Something")
l4.grid(row=0, column=3,)
something_lb = Entry(frame_entry)
something_lb.grid(row=1, column=3)


def select_record():
    logo_lb.delete(0,END) 
    name_lb.delete(0,END)
    lastname_lb.delete(0,END)
    something_lb.delete(0,END)

    selected = json_tree.focus() 
    values = json_tree.item(selected,'values')

    logo_lb.insert(0, values[0]) 
    name_lb.insert(0,values[1])
    lastname_lb.insert(0,values[2])
    something_lb.insert(0,values[3])

select_btn = tk.Button(frame2, text="Select", command=select_record)
select_btn.pack(side=LEFT, ipadx=30,)

def update_record():        
    selected = json_tree.focus()
    json_tree.item(selected, text='', values=(str(logo_lb.get()),str(name_lb.get()),str(lastname_lb.get()),str(something_lb.get()))) 
    
    with open('prueba1.json', "r") as f:
        data = json.load(f)
        temp = data["Example"]
        y = {
                    "Logo": str(logo_lb.get()),
                    "Name": str(name_lb.get()),
                    "Last Name": str(lastname_lb.get()),
                    "Something": str(something_lb.get()),
                    
                    }
        temp.append(y)

    with open('prueba1.json', 'w') as f:
        json.dump(data, f, indent=4)
    
    logo_lb.delete(0,END) 
    name_lb.delete(0,END)
    lastname_lb.delete(0,END)
    something_lb.delete(0,END)

update_btn = tk.Button(frame2, text="Update", command=update_record)
update_btn.pack(side=RIGHT,ipadx=30, pady=10)

ventana.mainloop()

How json looks like

{
    "Example": [
        {
            "Logo": "C:/Users/*/Desktop/Tkinter/logos/selavalacarita.png",
            "Name": "2",
            "Last Name": "3",
            "Something": "4"
        },
        {
            "Logo": "C:/Users/*/Desktop/Tkinter/logos/selavalacarita.png",
            "Name": "1",
            "Last Name": "4",
            "Something": "7"
        }
    ]
}
Comments:
2023-01-20 00:30:13
I have shown you how to save the data in a treeview to a JSON file in your another question.
2023-01-20 00:30:13
Yes, i tried to save it using json.dump({'Example': data}, f, indent=4), and data contains the json_tree.item. In the treeview I select the item and save the update but in the json deletes everything previous. Sorry for being so annoying, but I've seen very little of back, I usually only do frontend.
Answers(1) :

You don't need to read the JSON file again, just save the data of the treeview to the file after the selected item is updated:

def update_record():
    selected = json_tree.focus()
    json_tree.item(selected, text='', values=(str(logo_lb.get()),str(name_lb.get()),str(lastname_lb.get()),str(something_lb.get()))) #guardar data

    # update the JSON file
    columns = ("Logo", "Name", "Last Name", "Something")
    data = [dict(zip(columns,json_tree.item(iid,"values"))) for iid in json_tree.get_children()]
    with open("prueba1.json", "w") as f:
        json.dump({"Example":data}, f, indent=4)

    #Limpiar las cajas
    logo_lb.delete(0, END)
    name_lb.delete(0, END)
    lastname_lb.delete(0, END)
    something_lb.delete(0, END)

I would suggest to use database (like SQLite) instead of JSON file for storing those records.