Explanation: On Clicking submit button, the entries should appear in tree.
I have restricted the entries fields so they can take only two values (using trace method).
Problem 1: I have a total of 8 entries, which means the code has 8 StringVar, 8 entry, 8 label, 1 button and a total of 17 grids. Please help me to reduce the code.
Problem 2: I need entries in one list which I can use globally.
from tkinter import Tk, Frame, Button, Label, Entry, ttk, StringVar, Scrollbar
import datetime
# Main Window
class WINDOW(Tk):
def __init__(self, master):
Tk.__init__(self, master)
self.master = master
frame1 = Frame1(self)
frame1.grid(row=0,column=0)
list_of_entries=[]
class Frame1(Frame):
def __init__(self, master):
Frame.__init__(self, master,height=master.winfo_screenheight(),
width=master.winfo_screenwidth())
self.master = master
one_var = StringVar()
two_var = StringVar()
three_var = StringVar()
four_var = StringVar()
five_var = StringVar()
# Restrict entry field for 2 values only (using trace)
one_var.trace("w", lambda name, index, mode, one_var=one_var: callback())
two_var.trace("w", lambda name, index, mode, two_var=one_var: callback())
three_var.trace("w", lambda name, index, mode, three_var=one_var: callback())
four_var.trace("w", lambda name, index, mode, four_var=one_var: callback())
five_var.trace("w", lambda name, index, mode, five_var=one_var: callback())
def callback(*args):
one_var.set(one_var.get()[:2])
two_var.set(two_var.get()[:2])
three_var.set(three_var.get()[:2])
four_var.set(four_var.get()[:2])
five_var.set(five_var.get()[:2])
# Request frame labels
DATA0_lbl = Label(self, text='DATA0', font=('calibre', 10, 'bold'))
DATA1_lbl = Label(self, text='DATA1', font=('calibre', 10, 'bold'))
DATA2_lbl = Label(self, text='DATA2', font=('calibre', 10, 'bold'))
DATA3_lbl = Label(self, text='DATA3', font=('calibre', 10, 'bold'))
DATA4_lbl = Label(self, text='DATA4', font=('calibre', 10, 'bold'))
# Request frame label grid
DATA0_lbl.grid(row=0, column=0)
DATA1_lbl.grid(row=0, column=1)
DATA2_lbl.grid(row=0, column=2)
DATA3_lbl.grid(row=0, column=3)
DATA4_lbl.grid(row=0, column=4)
# Request frame entry fields
DATA0_entry = Entry(self,textvariable=one_var, width=10, font=('calibre', 10, 'normal'))
DATA1_entry = Entry(self,textvariable=two_var, width=10, font=('calibre', 10, 'normal'))
DATA2_entry = Entry(self, textvariable=three_var, width=10, font=('calibre', 10, 'normal'))
DATA3_entry = Entry(self,textvariable=four_var, width=10, font=('calibre', 10, 'normal'))
DATA4_entry = Entry(self, textvariable=five_var, width=10, font=('calibre', 10, 'normal'))
# Request frame entry field grid
DATA0_entry.grid(row=1, column=0)
DATA1_entry.grid(row=1, column=1)
DATA2_entry.grid(row=1, column=2)
DATA3_entry.grid(row=1, column=3)
DATA4_entry.grid(row=1, column=4)
# Log data sheet
NewTree = ttk.Treeview(self, height=23, columns=("DATA0","DATA1", "DATA2", "DATA3","DATA4"))
NewTree.column("#0", width=180)
NewTree.column("#1", width=150)
NewTree.column("#2", width=150)
NewTree.column("#3", width=150)
NewTree.column("#4", width=150)
NewTree.column("#5", width=150)
NewTree.heading("#0",text='TIME')
NewTree.heading("#1",text='DATA0')
NewTree.heading("#2",text='DATA1')
NewTree.heading("#3",text='DATA2')
NewTree.heading("#4",text="DATA3")
NewTree.heading("#5", text="DATA4")
NewTree.grid(row=5, columnspan=4)
def insert_data():
NewTree.insert('', 'end', text=datetime.datetime.now(),
values=(DATA0_entry.get(),
DATA1_entry.get(),
DATA2_entry.get(),
DATA3_entry.get(),
DATA4_entry.get()))
one_var.set("")
two_var.set("")
three_var.set("")
four_var.set("")
five_var.set("")
submit_button = Button(self, text="SUBMIT", command=insert_data)
submit_button.grid(row=3, column=4)
root = WINDOW(None)
root.geometry(f'{root.winfo_screenwidth()}x{root.winfo_screenheight()}')
root.title("ADD DATA")
root.mainloop()
You can use a loop to create the entries and labels. By using the validation feature of the entry widgets rather than the trace, you can throw away the trace statements and the instances of StringVar
completely.
All combined, this will end up reducing the code by about 50 lines or so.
For a detailed explanation of entry validation, see Interactively validating Entry widget content in tkinter
Here's a complete example:
from tkinter import Tk, Frame, Button, Label, Entry, ttk, StringVar, Scrollbar
import datetime
# Main Window
class WINDOW(Tk):
def __init__(self, master):
Tk.__init__(self, master)
self.master = master
frame1 = Frame1(self)
frame1.grid(row=0,column=0)
list_of_entries=[]
class Frame1(Frame):
def __init__(self, master):
Frame.__init__(self, master,height=master.winfo_screenheight(),
width=master.winfo_screenwidth())
self.master = master
vcmd = (self.register(self.validate), '%P')
self.entries = []
for i in range(5):
label = Label(self, text=f"DATA{i}", font=('calibre', 10, 'bold'))
entry = Entry(self, validatecommand=vcmd, validate='key', width=10, font=('calibre', 10, 'normal'))
label.grid(row=0, column=i)
entry.grid(row=1, column=i)
self.entries.append(entry)
# Log data sheet
NewTree = ttk.Treeview(self, height=23, columns=("DATA0","DATA1", "DATA2", "DATA3","DATA4"))
NewTree.column("#0", width=180)
NewTree.column("#1", width=150)
NewTree.column("#2", width=150)
NewTree.column("#3", width=150)
NewTree.column("#4", width=150)
NewTree.column("#5", width=150)
NewTree.heading("#0",text='TIME')
NewTree.heading("#1",text='DATA0')
NewTree.heading("#2",text='DATA1')
NewTree.heading("#3",text='DATA2')
NewTree.heading("#4",text="DATA3")
NewTree.heading("#5", text="DATA4")
NewTree.grid(row=5, columnspan=4)
def insert_data():
NewTree.insert('', 'end', text=datetime.datetime.now(),
values=(self.entries[0].get(),
self.entries[1].get(),
self.entries[2].get(),
self.entries[3].get(),
self.entries[4].get()))
for i in range(5):
self.entries[i].delete(0, 'end')
submit_button = Button(self, text="SUBMIT", command=insert_data)
submit_button.grid(row=3, column=4)
def validate(self, new_value):
return len(new_value) <= 2
root = WINDOW(None)
root.geometry(f'{root.winfo_screenwidth()}x{root.winfo_screenheight()}')
root.title("ADD DATA")
root.mainloop()