Home > Mobile >  define tkentry using a loop over a dictionary
define tkentry using a loop over a dictionary

Time:10-26

I am newbie to tkinter and OOP and I am trying to build a GUI that creates entries using a for loop. Basically it should:

  • read a dictionary and use its keys as tk.Labels
  • use its last two values as predefined values for the two tkinter entries (each label should have two antries).
  • Each entry should have a checkbox that disable/enables the second entry for each row
  • Use a button to update the dictionay's values

I have written the following modules:

import tkinter as tk

def create_input_dictionary():
    out = {'Header 1': ['DATA', 'Min', 'Max'],
           'Do': ['Lab1', 'mm', '25', '35'],
           'Di': ['Lab1', 'mm', '25', '35'],
           'nos': ['Lab9', '10']
           }
    return out

def isfloat(value):
    """The function checks if an element is a number"""
    try:
        float(value)
        return True
    except ValueError:
        return False

def allarefloats(var_list):
    """The function checks if all the elements in the lists are numbers"""
    check = True
    for item in var_list:
        check = check and isfloat(item)
    return check

class gui:
    '''this is a classe that creates an instance of the GUI'''
    def __init__(self, master):  # , container, input_dict):  # , *args, **kwargs):
        self.master = master
        self.ck1 = []
        self.ent1 = []
        self.ent2 = []

    def make_entry(self, container, input_dict):
        self.container = container
        self.input_dict = input_dict
        self.entry_col1 = tk.StringVar()
        self.entry_col2 = tk.StringVar()
        self.label_entry = tk.StringVar()
        self.nac = [tk.IntVar()] * len(input_dict)

        for ind, key in enumerate(self.input_dict):

            if 'Header' not in key:
                n = 0
                if key != 'nos':
                    self.ck1.append(tk.Checkbutton(self.container, variable=self.nac[n], command=lambda: self.naccheck()))
                    self.ck1[-1].grid(row=ind, column=0, sticky='ns')
                    n  = 1
                    label = self.input_dict[key][0]   '('   self.input_dict[key][1]   ')'
                    tk.Label(self.container, text=label).grid(row=ind, column=1, sticky='nw')

                    self.ent1.append(
                        tk.Entry(self.container, width=10, background='white',
                                 textvariable=self.entry_col1, state='normal'))
                    self.ent1[-1].grid(row=ind, column=2, sticky='ns')

                    self.ent2.append(tk.Entry(self.container, width=10, background='white',
                                              textvariable=self.entry_col2, state='disabled'))
                    self.ent2[-1].grid(row=ind, column=3, sticky='ns')
                else:
                    label = self.input_dict[key][0]
                    tk.Label(self.container, text=label).grid(row=ind, column=0, columnspan=2, sticky='ns')
                    self.ent1[-1] = tk.Entry(self.container, width=10, background='white',
                                             textvariable=self.entry_col1, state='normal')
                    self.ent1[-1].grid(row=ind, column=2, columnspan=2, sticky='ns')

    def naccheck(self):
        if self.nac[-1].get() == 0:
            self.ent2[-1].configure(state='disabled')
        else:
            self.ent2[-1].configure(state='normal')


if __name__ == '__main__':
    main_root = tk.Tk()

    input_frame = tk.Frame(main_root, padx=10, pady=5)
    input_frame.grid(row=0, sticky='ns')

    input_steps = tk.Frame(main_root, padx=10, pady=5)
    input_steps.grid(row=1, sticky='ns')

    button_first_frame = tk.Frame(main_root, padx=10, pady=5)
    button_first_frame.grid(row=2, sticky='ns')

    dict_inp = create_input_dictionary()

    gui = gui(main_root)
    gui.make_entry(input_frame, dict_inp)

    button = tk.Button(button_first_frame, text="click me", command=lambda: print(dict_inp))
    button.grid(row=0, columnspan=3)

    main_root.mainloop()

But I cannot figure out why the entries and checkboxes are dependent

CodePudding user response:

Here is one approach:

import tkinter as tk


out = {
    'Header 1': ['DATA', 'Min', 'Max'],
    'Do': ['Lab1', 'mm', '25', '35'],
    'Di': ['Lab1', 'mm', '25', '35'],
    'nos': ['Lab9', '10']
}


class DataRow(tk.Frame):
    def __init__(self, parent, label, lst, **kwargs):
        super().__init__(parent, **kwargs)
        self.lst = lst
        self.columnconfigure(tuple(range(4)), weight=1, minsize=100)

        tk.Label(self, text=label).grid(row=0, column=0, sticky='w')

        self.entry1 = tk.Entry(self)
        self.entry1.grid(row=0, column=1)
        self.entry1.insert('end', lst[-2])

        self.entry2 = tk.Entry(self)
        self.entry2.grid(row=0, column=3)
        self.entry2.insert('end', lst[-1])

        self.var = tk.IntVar(master=self, value=1)
        self.check = tk.Checkbutton(
            self, text='Enabled', command=self.enabled, onvalue=1, offvalue=0,
            variable=self.var
        )
        self.check.grid(row=0, column=2)

    def enabled(self):
        if self.var.get():
            self.entry2.config(state='normal')
        else:
            self.entry2.config(state='disabled')

    def update_data(self):
        self.lst[-2:] = self.entry1.get(), self.entry2.get()


def update_dict():
    for row in data_rows:
        row.update_data()


root = tk.Tk()
data_rows = []

for key, value in out.items():
    dr = DataRow(root, key, value)
    dr.pack(expand=True, fill='both')
    data_rows.append(dr)


tk.Button(
    root, text='Update', command=update_dict
).pack(side='bottom', expand=True, fill='both')

root.mainloop()

Create a class that will represent one of the rows, in the class simply define the label, the two entries and the checkbutton, create methods for updating the lists and a method for enabling the button. Then create these rows in a loop iterating over the dictionary and add the DataRows to a list. Then assign a function to the button that will go over that list and call the updating functions on each data row, that will update the lists.

  • Related