减少代码行数(tkinter,Python,多个标签,条目)
Reduce the lines of code (tkinter, Python, Multiple labels, entry)
解释:点击提交按钮,条目应该出现在树中。
我限制了条目字段,因此它们只能取两个值(使用跟踪方法)。
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()
您可以使用循环来创建条目和标签。通过使用条目小部件的验证功能而不是跟踪,您可以完全丢弃跟踪语句和 StringVar
的实例。
所有这些结合起来,最终会减少大约 50 行左右的代码。
有关条目验证的详细说明,请参阅Interactively validating Entry widget content in tkinter
这是一个完整的例子:
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()
首先,您可以通过使用 for
循环完全减少代码,您可以放弃使用 StringVar
而是使用 tkinter
的验证,取看这里:
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) # Register the validation function
NewTree = ttk.Treeview(self, height=23, columns=("DATA0","DATA1", "DATA2", "DATA3","DATA4"))
NewTree.grid(row=5, columnspan=4)
NewTree.column("#0", width=180) # These column would stand out of the loop
NewTree.heading("#0",text='TIME') # So manually inserting them
MAX_WIDGETS = 5
base_text = 'DATA' # Base text, so later you can add 1 to make it DATA1 and so on..
lbls = [] # Empty list for label to append to later, not necessary if you dont need to change or reuse them later
self.entries = []
for i in range(MAX_WIDGETS):
NewTree.column(f"#{str(i+1)}", width=150) # i+1 because you have an extra column already
NewTree.heading(f"#{str(i+1)}",text=base_text+str(i))
lbls.append(Label(self, text=base_text+str(i), font=('calibre', 10, 'bold')))
lbls[i].grid(row=0, column=i)
self.entries.append(Entry(self, width=10, font=('calibre', 10, 'normal'),validate='key',validatecommand=(vcmd,'%P')))
self.entries[i].grid(row=1, column=i)
submit_button = Button(self, text="SUBMIT", command=lambda: self.insert_data(NewTree))
submit_button.grid(row=3, column=4)
def insert_data(self,tree):
data = [x.get() for x in self.entries]
tree.insert('', 'end', text=datetime.datetime.now(),
values=data)
[x.delete(0,'end') for x in self.entries] # Just to delete the items, list is otherwise of no use.
def validate(self,inp): # The validation function
return len(inp) <= 2
root = WINDOW(None)
root.geometry(f'{root.winfo_screenwidth()}x{root.winfo_screenheight()}')
root.title("ADD DATA")
root.mainloop()
我使用 for
尽可能地缩短了代码。有时不可能将内容保留在循环范围内,例如您额外的 TIME
列,所以我将其放在循环之外。并且由于您正在使用 类 ,因此可以最大限度地利用它,而不是定义函数、定义方法等。你之前的版本大概是120行左右,现在减少到60行左右。
您还可以进一步使用更多的 LC(列表理解),但我认为这可能会降低代码的可读性,因为这是在编写代码时要牢记的一个重要因素。
您可以取消向列表附加标签,如果您不打算重复使用它们,它将节省 1 行额外的代码;)
要更好地理解验证,请查看:Interactively validating Entry widget content in tkinter
解释:点击提交按钮,条目应该出现在树中。
我限制了条目字段,因此它们只能取两个值(使用跟踪方法)。
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()
您可以使用循环来创建条目和标签。通过使用条目小部件的验证功能而不是跟踪,您可以完全丢弃跟踪语句和 StringVar
的实例。
所有这些结合起来,最终会减少大约 50 行左右的代码。
有关条目验证的详细说明,请参阅Interactively validating Entry widget content in tkinter
这是一个完整的例子:
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()
首先,您可以通过使用 for
循环完全减少代码,您可以放弃使用 StringVar
而是使用 tkinter
的验证,取看这里:
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) # Register the validation function
NewTree = ttk.Treeview(self, height=23, columns=("DATA0","DATA1", "DATA2", "DATA3","DATA4"))
NewTree.grid(row=5, columnspan=4)
NewTree.column("#0", width=180) # These column would stand out of the loop
NewTree.heading("#0",text='TIME') # So manually inserting them
MAX_WIDGETS = 5
base_text = 'DATA' # Base text, so later you can add 1 to make it DATA1 and so on..
lbls = [] # Empty list for label to append to later, not necessary if you dont need to change or reuse them later
self.entries = []
for i in range(MAX_WIDGETS):
NewTree.column(f"#{str(i+1)}", width=150) # i+1 because you have an extra column already
NewTree.heading(f"#{str(i+1)}",text=base_text+str(i))
lbls.append(Label(self, text=base_text+str(i), font=('calibre', 10, 'bold')))
lbls[i].grid(row=0, column=i)
self.entries.append(Entry(self, width=10, font=('calibre', 10, 'normal'),validate='key',validatecommand=(vcmd,'%P')))
self.entries[i].grid(row=1, column=i)
submit_button = Button(self, text="SUBMIT", command=lambda: self.insert_data(NewTree))
submit_button.grid(row=3, column=4)
def insert_data(self,tree):
data = [x.get() for x in self.entries]
tree.insert('', 'end', text=datetime.datetime.now(),
values=data)
[x.delete(0,'end') for x in self.entries] # Just to delete the items, list is otherwise of no use.
def validate(self,inp): # The validation function
return len(inp) <= 2
root = WINDOW(None)
root.geometry(f'{root.winfo_screenwidth()}x{root.winfo_screenheight()}')
root.title("ADD DATA")
root.mainloop()
我使用 for
尽可能地缩短了代码。有时不可能将内容保留在循环范围内,例如您额外的 TIME
列,所以我将其放在循环之外。并且由于您正在使用 类 ,因此可以最大限度地利用它,而不是定义函数、定义方法等。你之前的版本大概是120行左右,现在减少到60行左右。
您还可以进一步使用更多的 LC(列表理解),但我认为这可能会降低代码的可读性,因为这是在编写代码时要牢记的一个重要因素。
您可以取消向列表附加标签,如果您不打算重复使用它们,它将节省 1 行额外的代码;)
要更好地理解验证,请查看:Interactively validating Entry widget content in tkinter