我创建了自己的 Dialog 类版本,该类用作具有自定义字段的不同对话框窗口的父类。底部是 Dialog 类的代码。在其中一个对话框类型窗口中有一个组合框(下拉框),它允许用户也输入他们自己的值。如果他们输入自己的值(他们的名字)并且它不包含在客户列表中(来自文件),它会询问用户是否要添加新客户。如果他们选择是,我希望它将他们输入的名称传递给父窗口(应用程序的根),关闭他们输入名称的对话框,然后打开另一个对话框以输入新客户的信息(包含他们之前输入的名称)。除了向上传递值之外,这一切都有效。
我应该如何传递这个值?我最初的想法是通过自定义 Tkinter 事件。我找不到有关如何执行此操作的信息。
创建第一个子对话框的根方法:
def check_in(self):
log_diag = LoggerDialog(self,self.customers)
try:
log_diag.show()
except NewCustomerException, (instance):
self.new_customer(str(instance))
except:
print instance
内部子对话框:
def new_customer_error(self):
#parse name and preset values in the new customer dialog
name = self.name.get()
if askquestion(title="New Customer?",
message="Add new customer: " + name,
parent = self.root) == 'yes':
raise NewCustomerException(name)
对话类:
class Dialog:
def __init__(self, master, title, class_=None, relx=0.5, rely=0.3):
self.master = master
self.title = title
self.class_ = class_
self.relx = relx
self.rely = rely
def setup(self):
if self.class_:
self.root = Toplevel(self.master, class_=self.class_)
else:
self.root = Toplevel(self.master)
self.root.title(self.title)
self.root.iconname(self.title)
def enable(self):
### enable
self.root.protocol('WM_DELETE_WINDOW', self.wm_delete_window)
self._set_transient(self.relx, self.rely)
self.root.wait_visibility()
self.root.grab_set()
self.root.mainloop()
self.root.destroy()
def _set_transient(self, relx=0.5, rely=0.3):
widget = self.root
widget.withdraw() # Remain invisible while we figure out the geometry
widget.transient(self.master)
widget.update_idletasks() # Actualize geometry information
if self.master.winfo_ismapped():
m_width = self.master.winfo_width()
m_height = self.master.winfo_height()
m_x = self.master.winfo_rootx()
m_y = self.master.winfo_rooty()
else:
m_width = self.master.winfo_screenwidth()
m_height = self.master.winfo_screenheight()
m_x = m_y = 0
w_width = widget.winfo_reqwidth()
w_height = widget.winfo_reqheight()
x = m_x + (m_width - w_width) * relx
y = m_y + (m_height - w_height) * rely
if x+w_width > self.master.winfo_screenwidth():
x = self.master.winfo_screenwidth() - w_width
elif x < 0:
x = 0
if y+w_height > self.master.winfo_screenheight():
y = self.master.winfo_screenheight() - w_height
elif y < 0:
y = 0
widget.geometry("+%d+%d" % (x, y))
widget.deiconify() # Become visible at the desired location
def wm_delete_window(self):
self.root.quit()
我尝试使用 generate_event() 并传递自定义参数(名称),但出现此错误:
TclError: bad option "-name": must be -when, -above, -borderwidth,
-button, -count, -data, -delta, -detail, -focus, -height, -keycode,
-keysym, -mode, -override, -place, -root, -rootx, -rooty, -sendevent,
-serial, -state, -subwindow, -time, -warp, -width, -window, -x, or -y
我已经尝试覆盖其中一些的值,但我不断收到错误消息,告诉我我传递了错误的类型。(mode 是一个 int,detail 必须是特定对象列表的实例)这似乎不是一个非常优雅的解决方案。
这是我确定的解决方案:
子对象中的代码(用于处理不在数据库中的名称):
def new_customer_error(self):
if askquestion(title="New Customer?",
message="Add new customer: " + self.name.get(),
parent = self.root) == 'yes':
self.master.event_generate('<<NewCustomer>>')
在__init__
根窗口中:
self.bind('<<NewCustomer>>',self.new_customer)
稍后在根对象中:
def new_customer(self, event=None):
#if evert this came as a new customer entry through check in
if event:
temp = self.logger_diag.name.get().split(' ')
self.newc_diag.fname.set(temp[0])
if len(temp) == 2:
self.newc_diag.lname.set(temp[1])
elif len(temp) == 3:
self.newc_diag.mname.set(temp[1])
self.newc_diag.lname.set(temp[2])
elif len(temp) > 3:
self.newc_diag.mname.set(temp[1])
self.newc_diag.lname.set(' '.join(temp[2:4]))