1

I am trying to display a simple Python dictionary in a tkinter Treeview widget. I have adapted some code I found here to my purpose, but I can't get the code to display more than the first word of each of the values in the lists of strings in the dictionary.

My guess it is something with the way the treeview columns are set up that is limiting the display to one word, but I can't figure out the right flag to tweak. I have left some false starts in the code as commented lines.

# Credit to https://stackoverflow.com/a/22722889/122364
import uuid
import tkinter as tk
from tkinter import ttk, filedialog
import os

#Code is working OK other than clipping of each string in dictionary to first word.

TestData = {
    "DATE": [
        "1916",
        "1935",
        "2019",
        "2020",
        "29 January 2016",
        "31st of March",
        "3rd day of March",
        "5 June 2019",
        "5/6/2019",
        "5th June 2019",
        "March",
        "March 3rd, 2015"
    ],
    "ORG": [
        "Merril Lynch",
        "Goldman Sachs"
    ],
    "TIME": [],
}

def Convert(lst): 
    res_dct = {i: lst[i] for i in range(0, len(lst))} 
    return res_dct 

def json_tree(tree, parent, dictionary):
    for key in dictionary:
        uid = uuid.uuid4()
        if isinstance(dictionary[key], dict):
            tree.insert(parent, 'end', uid, text=dictionary[key])
##            tree.insert(parent, 'end', uid, text=key)
            json_tree(tree, uid, dictionary[key])
        elif isinstance(dictionary[key], list):
##            print("list found")
            print(dictionary[key])
            tree.insert(parent, 'end', uid, text=key)
            json_tree(tree,
                      uid,
##                      dict(i for i in enumerate(tuple(dictionary[key]))))
                      Convert(dictionary[key]))
##                      dict([(i, x) for i, x in enumerate(dictionary[key])]))
        elif isinstance(dictionary[key], tuple):
            tree.insert(parent, 'end', uid, text=key + '[]')
            json_tree(tree,
                      uid,
                      dict([(i, x) for i, x in enumerate(dictionary[key])]))
        else:
            value = dictionary[key]
            if value is None:
                value = 'None'
            tree.insert(parent, 'end', uid, text=key, value=value)


def show_data(data):
    # Setup the root UI
    root = tk.Tk()
    root.title("JSON viewer")
    root.columnconfigure(0, weight=1)
    root.rowconfigure(0, weight=1)

    # Setup the Frames
    tree_frame = ttk.Frame(root, padding="3")
    tree_frame.grid(row=0, column=0, sticky=tk.NSEW)

    # Setup the Tree
    tree = ttk.Treeview(tree_frame, columns='Values', selectmode="extended")
    tree.column('Values', width=100, anchor='center')
    tree.heading('Values', text='Values')
    json_tree(tree, '', data)
    tree.pack(fill=tk.BOTH, expand=1)

    # Limit windows minimum dimensions
    root.update_idletasks()
    root.minsize(800, 800)
    root.mainloop()

if __name__ == '__main__':
    show_data(TestData)
martineau
  • 119,623
  • 25
  • 170
  • 301
lalau66
  • 19
  • 2
  • I found a partial solution - to replace spaces in the input strings (my data is mainly strings) with hard spaces. if isinstance(value, str) or isinstance(value, unicode): value = value.replace(' ', "\u00A0") #stripping done to avoid a ttk module error created by quotes within strings Tree.insert(Parent, 'end', uid, text=key, value=str(value).replace('"','')) My question now is whether there is a cleaner way to avoid this issue that doesn't involve replacing any characters. – lalau66 Jan 25 '20 at 00:36
  • row may have many columns and `value=` (and `values=`) is treated as list of data - and string is splited on words as list of data - but if you use list `value=[value]` or tuple `value=(value,)` then you get full text in column. – furas Jan 25 '20 at 09:21
  • eventually you would put all text in `" "` - `value='"{}"'.format(value)` and it should treats it as single element – furas Jan 25 '20 at 09:27
  • Thanks for the suggestions. The list and tuple methods introduce undesirable container characters, while the second suggestion doesn't fix the problem. For now, I am stuck with the whitespace replacement but this creates issues with the data. – lalau66 Jan 27 '20 at 00:36

0 Answers0