Last active
July 16, 2021 16:15
-
-
Save wware/a1d90a3ca3cbef31ed3fbb7002fd1318 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
I've modified John Gaines Jr.'s answer to handle lists. I didn't need editing | |
or the Taglist for what I'm doing so I removed them. They could certainly be | |
added back. Since lists can introduce duplication of keys, I replaced the keys | |
with UUIDs while still showing the original key as text on the left side of the | |
treeview. | |
UPDATE: My original answer did not include the editing function that John Gaines Jr. | |
had implemented. I've now added that to mine, with the caveat that I'm not very | |
expert regarding Tk/Tkinter layout and spacing, so I stopped tinkering once it | |
looked OK on my machine. | |
""" | |
import json | |
import uuid | |
import Tkinter as tk | |
import ttk | |
from pprint import pprint as pprint | |
# opt_name: (from_, to, increment) | |
IntOptions = { | |
'age': (1.0, 200.0, 1.0), | |
} | |
def close_ed(parent, edwin): | |
parent.focus_set() | |
edwin.destroy() | |
def set_cell(edwin, w, tvar): | |
value = tvar.get() | |
w.item(w.focus(), values=(value,)) | |
close_ed(w, edwin) | |
def edit_cell(e): | |
w = e.widget | |
if w and len(w.item(w.focus(), 'values')) > 0: | |
edwin = tk.Toplevel(e.widget) | |
edwin.protocol("WM_DELETE_WINDOW", lambda: close_ed(w, edwin)) | |
edwin.wait_visibility() | |
edwin.grab_set() | |
edwin.overrideredirect(1) | |
opt_name = w.focus() | |
(x, y, width, height) = w.bbox(opt_name, 'Values') | |
edwin.geometry('%dx%d+%d+%d' % (width, height, x/4, y)) | |
value = w.item(opt_name, 'values')[0] | |
tvar = tk.StringVar() | |
tvar.set(str(value)) | |
ed = None | |
if opt_name in IntOptions: | |
constraints = IntOptions[opt_name] | |
ed = tk.Spinbox(edwin, from_=constraints[0], to=constraints[1], | |
increment=constraints[2], textvariable=tvar) | |
else: | |
ed = tk.Entry(edwin, textvariable=tvar) | |
if ed: | |
ed.config(background='LightYellow') | |
#ed.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.W, tk.E)) | |
ed.pack() | |
ed.focus_set() | |
edwin.bind('<Return>', lambda e: set_cell(edwin, w, tvar)) | |
edwin.bind('<Escape>', lambda e: close_ed(w, edwin)) | |
def JSONTree(Tree, Parent, Dictionary): | |
for key in Dictionary : | |
uid = uuid.uuid4() | |
if isinstance(Dictionary[key], dict): | |
Tree.insert(Parent, 'end', uid, text=key) | |
JSONTree(Tree, uid, Dictionary[key]) | |
elif isinstance(Dictionary[key], list): | |
Tree.insert(Parent, 'end', uid, text=key + '[]') | |
JSONTree(Tree, | |
uid, | |
dict([(i, x) for i, x in enumerate(Dictionary[key])])) | |
else: | |
value = Dictionary[key] | |
if isinstance(value, str) or isinstance(value, unicode): | |
value = value.replace(' ', '_') | |
Tree.insert(Parent, 'end', uid, text=key, value=value) | |
if __name__ == "__main__" : | |
# Setup the root UI | |
root = tk.Tk() | |
root.title("JSON editor") | |
root.columnconfigure(0, weight=1) | |
root.rowconfigure(0, weight=1) | |
# Setup Data | |
Data = { | |
"firstName": "John", | |
"lastName": "Smith", | |
"gender": "male", | |
"age": 32, | |
"address": { | |
"streetAddress": "21 2nd Street", | |
"city": "New York", | |
"state": "NY", | |
"postalCode": "10021"}, | |
"phoneNumbers": [ | |
{"type": "home", "number": "212 555-1234" }, | |
{"type": "fax", | |
"number": "646 555-4567", | |
"alphabet": [ | |
"abc", | |
"def", | |
"ghi"] | |
} | |
]} | |
# Setup the Frames | |
TreeFrame = ttk.Frame(root, padding="3") | |
TreeFrame.grid(row=0, column=0, sticky=tk.NSEW) | |
# Setup the Tree | |
tree = ttk.Treeview(TreeFrame, columns=('Values')) | |
tree.column('Values', width=100, anchor='center') | |
tree.heading('Values', text='Values') | |
tree.bind('<Double-1>', edit_cell) | |
tree.bind('<Return>', edit_cell) | |
JSONTree(tree, '', Data) | |
tree.pack(fill=tk.BOTH, expand=1) | |
# Limit windows minimum dimensions | |
root.update_idletasks() | |
root.minsize(root.winfo_reqwidth(), root.winfo_reqheight()) | |
root.mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment