在下面的代码中,我设法部分验证了输入到 self.e2 条目小部件中的数据,不幸的是,如果条目小部件为空并且按下了提交按钮,则会生成 ValueError”ValueError: invalid literal for int() with base 10: '' " 我想让程序识别 e2 条目小部件为空,捕获 ValueError 并将焦点返回到条目小部件。
我试图使用 is_valid_int 和 invalid_int 方法来做到这一点,但这不起作用。
from tkinter import *
from tkinter import ttk
from tkinter.scrolledtext import *
class DailyOrderGUI:
def __init__(self, parent):
#Data entring frame
self.frame = Frame(parent, bg = "grey")
self.frame.grid(row=0)
self.label1 = Label(self.frame, text = "Mrs CackleBerry's Egg Ordering System", wraplength = 200, bg="grey", font=("Comic Sans MS", "14", "bold"))
self.label1.grid(row = 0, columnspan = 3, padx = 5, pady = 5)
self.superegg_img = PhotoImage(file = "images/superegg.gif")
self.label5 = Label(self.frame, bg="grey", image = self.superegg_img)
self.label5.grid(row = 0, column= 3, padx = 5, pady = 5)
self.v = StringVar()
self.v.set("Monday")
self.label2 = Label(self.frame, text = "Which day are you ordering for?", bg="grey", font=("Arial", "12", "bold"))
self.label2.grid(row = 1, columnspan = 4, sticky = W)
self.rb1 = Radiobutton(self.frame, variable = self.v, bg="grey", value = "Monday", text = "Monday")
self.rb1.grid(row = 2, column = 0, sticky = W)
self.rb2 = Radiobutton(self.frame, variable = self.v, bg="grey", value = "Tuesday", text = "Tuesday")
self.rb2.grid(row = 2, column = 1, sticky = W)
self.rb3 = Radiobutton(self.frame, variable = self.v, bg="grey", value = "Wednesday", text = "Wednesday")
self.rb3.grid(row = 2, column = 2, sticky = W)
self.rb4 = Radiobutton(self.frame, variable = self.v, bg="grey", value = "Thursday", text = "Thursday")
self.rb4.grid(row = 2, column = 3, sticky = W)
self.rb5 = Radiobutton(self.frame, variable = self.v, bg="grey", value = "Friday", text = "Friday")
self.rb5.grid(row = 3, column = 0, sticky = W)
self.rb6 = Radiobutton(self.frame, variable = self.v, bg="grey", value = "Saturday", text = "Saturday")
self.rb6.grid(row = 3, column = 1, sticky = W)
self.rb7 = Radiobutton(self.frame, variable = self.v, bg="grey", value = "Sunday", text = "Sunday")
self.rb7.grid(row = 3, column = 2, sticky = W)
self.label3 = Label(self.frame, text = "Customer's Name:?(Press \"Orders Complete\" to finish)", bg="grey", font=("Arial", "12", "bold"))
self.label3.grid(row = 4, columnspan = 4,padx = 5, sticky = W)
self.e1 = Entry(self.frame, width = 30)
self.e1.grid(row = 5, columnspan = 4, sticky = W, padx = 5, pady=3)
self.e1.focus()
self.label4 = Label(self.frame, text = "How many eggs being ordered:?", bg="grey", font=("Arial", "12", "bold"))
self.label4.grid(row = 6, columnspan = 4,padx = 5,sticky = W)
integer = self.create_integer_widget()
self.btn1 = Button(self.frame, text = "Submit")
self.btn1.grid(row = 8, padx = 5, pady = 3, sticky = E+W)
self.btn1.bind("<Button-1>", self.get_orders)
self.btn2 = Button(self.frame, text = "Orders Complete", command = self.show_summary_result)
self.btn2.grid(row = 8, column = 3, padx = 5, pady = 3, sticky = E+W)
#Summary Frame
self.summ_frame = Frame(parent, bg = "grey")
self.summ_frame.grid(row=0)
self.summ_label1 = Label(self.summ_frame, text = "Mrs CackleBerry's Egg Ordering System", bg="grey", font=("Comic Sans MS", "14", "bold"))
self.summ_label1.grid(row = 0, columnspan = 4, padx = 5, pady = 5)
self.scrolled_display = ScrolledText(self.summ_frame, width = 50, height = 10, bg="thistle", font=("Times New Roman", "12"))
self.scrolled_display.grid(row = 1, columnspan = 2, padx = 5, pady = 20, sticky = W)
self.data_entry_btn = Button(self.summ_frame, text = "Back to Data Entry", command = self.show_data_entry_frame)
self.data_entry_btn.grid(row = 2, column = 0, sticky = SE, padx = 5, pady = 20)
self.egg_orders=[]
self.show_data_entry_frame()
def create_integer_widget(self):
self.e2 = ttk.Entry(self.frame, width = 10, validate='key')
self.e2['validatecommand'] = (self.frame.register(self.is_valid_int), '%P')
self.e2['invalidcommand'] = (self.frame.register(self.invalid_int), '%W')
self.e2.grid(row = 7, columnspan = 4, sticky = W, padx = 5, pady=3)
self.e2.bind("<Return>", self.get_orders)
return self.e2
def is_valid_int(self, txt):
# txt - value in %P
if not txt: # do not accept empty string
return False
try:
int(txt)
return True # accept integer
except ValueError: # not an integer
return False
def invalid_int(self, widgetName):
# called automatically when the
# validation command returns 'False'
# get entry widget
widget = self.frame.nametowidget(widgetName)
# clear entry
widget.delete(0, END)
# return focus to integer entry
widget.focus_set()
widget.bell()
def show_data_entry_frame(self):
self.summ_frame.grid_remove()
self.frame.grid()
root.update_idletasks()
def show_summary_result(self):
self.frame.grid_remove()
self.summ_frame.grid()
root.update_idletasks()
self.scrolled_display.delete('1.0', END)
if len(self.egg_orders) == 0:
self.scrolled_display.insert(END, "No Orders")
else:
total = 0
self.scrolled_display.insert(END, "Orders for " + self.v.get() + "\n")
for i in range(len(self.egg_orders)):
total += self.egg_orders[i].num_eggs
self.scrolled_display.insert(END, str(self.egg_orders[i]) + "\n")
self.scrolled_display.insert(END, "" + "\n")
self.scrolled_display.insert(END, "Summary for " + self.v.get() + "\n")
self.scrolled_display.insert(END, "" + "\n")
self.scrolled_display.insert(END, "Total eggs: " + str(total) + "\n")
self.scrolled_display.insert(END, "Dozens required: " + str(self.get_dozens(total)) + "\n")
average = 0
if len(self.egg_orders) > 0:
average = total / len(self.egg_orders)
self.scrolled_display.insert(END, "Average number of eggs per customer: {0:.1f}".format(average) + "\n")
def get_orders(self, event):
"""
Collects order information - name, number of eggs in a loop
"""
self.name = self.e1.get()
self.no_eggs = self.e2.get()
self.e1.delete(0, END)
self.e2.delete(0, END)
self.e1.focus()
self.egg_orders.append(EggOrder(self.name, self.no_eggs))
def get_dozens (self, total):
"""
returns whole number of dozens required to meet required number of eggs
"""
num_dozens = total//12
if total%12 != 0:
num_dozens += 1
return num_dozens
class EggOrder:
price_per_doz = 6.5
def __init__(self, name, num_eggs):
self.name = name
self.num_eggs = int(num_eggs)
def calc_price(self):
self.price = EggOrder.price_per_doz/12 * self.num_eggs
return self.price
def __str__(self):
return("{} ordered {} eggs. The price is ${:.2f}".format(self.name, self.num_eggs , self.calc_price()))
#main routine
if __name__== "__main__":
root = Tk()
root.title("Mrs Cackleberry's Egg Ordering Program")
frames = DailyOrderGUI(root)
root.mainloop()