Search code examples
pythonuser-interfacetkintertabssave

How to save the contents of dynamic tabs in a GUI with tkinter


I'm having trouble saving the contents of dynamic tabs in a GUI environment made with tkinter in Python. When I enter the contents and click the save button, the text file created only shows the contents of the last tab in the GUI. Here is the script I'm working with.

import tkinter as tk
from tkinter import ttk

variables = dict()

def add_vehicle_tab():
    v_info = ttk.Frame(tab_control)
    tab_control.add(v_info, text='Tab {}'.format(tab_control.index(tk.END)))
    #add content here

    variables['VEH_MAKE'] = tk.StringVar(value=' ')
    ttk.Label(v_info, text= 'VEH_MAKE').grid(row=2, column=0)
    ttk.Entry(v_info, textvariable=variables['VEH_MAKE']).grid(row=3, column=0,sticky=(tk.W+tk.E))
    
    variables['COLOR'] = tk.StringVar(value=' ')
    ttk.Label(v_info, text= 'COLOR').grid(row=4, column=0)
    ttk.Entry(v_info, textvariable=variables['COLOR']).grid(row=5, column=0,sticky=(tk.W+tk.E))    

    variables['YEAR'] = tk.IntVar(value=' ')
    ttk.Label(v_info, text= 'YEAR').grid(row=6, column=0)
    ttk.Entry(v_info, textvariable=variables['YEAR']).grid(row=7, column=0,sticky=(tk.W+tk.E))

    tab_content['Tab {}'] = variables

def save_tabs():
    global records_saved
    make = variables['VEH_MAKE'].get()
    color = variables['COLOR'].get()
    year = variables['YEAR'].get()
    with open("C:/tabs_data.txt", "w") as file:
        for index, content in tab_content.items():
            file.write(f'VEH_MAKE = {make}'), file.write('\n')
            file.write(f'COLOR = {color}'), file.write('\n')
            file.write(f'YEAR = {year}'), file.write('\n')

root = tk.Tk()
root.title('Vehicle tabs')
tab_control = ttk.Notebook(root)
tab_control.pack(expand=1, fill='both')
tab_content = {}
add_tab_button = tk.Button(root, text='Add vehicle tab', command=add_vehicle_tab)
add_tab_button.pack()

save_button = tk.Button(root, text="Save Tabs", command=save_tabs)
save_button.pack()
root.mainloop()

In the save_tabs() function, the script saves each item and then writes them to a new file. However, the script only saves the last tab. What do I need to do to this script to make it save all tabs?


Solution

  • Note that the content of variables are overwritten to store the last set of tkinter variables whenever add_vehicle_tab() is executed. Also same key "tab {}" is used for tab_content, so tab_content has always one item.

    To fix the issue:

    • change variables to local variable instead
    • use current tab name as the key of tab_content

    Below is the updated code required:

    ...
    #variables = dict()  # don't use global variable
    
    def add_vehicle_tab():
        v_info = ttk.Frame(tab_control)
    
        name = 'Tab {}'.format(tab_control.index(tk.END))
        tab_control.add(v_info, text=name)
    
        variables = {}  # use local variable
    
        variables['VEH_MAKE'] = tk.StringVar()
        ttk.Label(v_info, text= 'VEH_MAKE').grid(row=2, column=0)
        ttk.Entry(v_info, textvariable=variables['VEH_MAKE']).grid(row=3, column=0,sticky=(tk.W+tk.E))
    
        variables['COLOR'] = tk.StringVar()
        ttk.Label(v_info, text= 'COLOR').grid(row=4, column=0)
        ttk.Entry(v_info, textvariable=variables['COLOR']).grid(row=5, column=0,sticky=(tk.W+tk.E))
    
        variables['YEAR'] = tk.IntVar()
        ttk.Label(v_info, text= 'YEAR').grid(row=6, column=0)
        ttk.Entry(v_info, textvariable=variables['YEAR']).grid(row=7, column=0,sticky=(tk.W+tk.E))
    
        # use tab name as the key
        tab_content[name] = variables
    
    def save_tabs():
        with open("C:/tabs_data.txt", "w") as file:
            for name, variables in tab_content.items():
                make = variables['VEH_MAKE'].get()
                color = variables['COLOR'].get()
                year = variables['YEAR'].get()
                file.write(f'{name}:\n')
                file.write(f'VEH_MAKE = {make}\n')
                file.write(f'COLOR = {color}\n')
                file.write(f'YEAR = {year}\n')
    ...
    

    I would suggest to save the content in JSON format:

    import json
    ...
    
    def save_tabs():
        data = {name: {key:var.get() for key, var in variables.items()}
                for name, variables in tab_content.items()}
        with open("C:/tabs_data.json", "w") as file:
            json.dump(data, file, indent=4)