我正在使用this post中找到的这些日历模块作为我的程序,对导入稍作修改,使其适用于最新的python版本 .
我只是展示我认为对这个问题很重要的代码片段 .
所以我创建了一个用于警报的弹出窗口:
#class for pop-up windows for alerts, errors etc.
class PopUpAlert():
def __init__(self, alert='Alert!'):
self.root = tk.Tk()
tk.Label(self.root,
text=alert,
font="Verdana 15",
fg='red',
padx=10,
pady=5).pack(side=tk.TOP)
self.root.bind('<Return>', (lambda event: self.ok()))
tk.Button(self.root,
text='ok',
pady=10,
command=self.ok).pack(side=tk.TOP)
def ok(self):
print('ok clicked')
self.root.destroy()
函数 ok
仅供我测试函数是否被调用 . 此窗口在我的代码中完全正常,除非我尝试使用日历实现,其中 PopUpAlert
的"ok"按钮(应该销毁窗口)停止工作:
class CalendarDialog(tkSimpleDialog.Dialog):
"""Dialog box that displays a calendar and returns the selected date"""
def body(self, master):
self.calendar = ttkcalendar.Calendar(master)
self.calendar.pack()
def apply(self):
self.result = self.calendar.selection
def validate(self):
if self.calendar.selection == None:
PopUpAlert(alert='Please select a date or click cancel!')
return False
return True
日历有一个"ok"按钮,用于确认选择日期并关闭日历窗口 . 我试图做的是,如果他/她没有选择日期,用户不能单击"ok"关闭窗口 . 为此,我使用了函数 validate
,它是我的 CalendarDialog
继承的类 tkSimpleDialog.Dialog
中预定义的 . 我覆盖了我的 CalendarDialog
类中的函数来调用 PopUpAlert
,然后将 False
返回到父函数 ok
(在日历窗口上按下"Ok"按钮时调用):
def ok(self, event=None):
if not self.validate():
self.initial_focus.focus_set() # put focus back
return
self.withdraw()
self.update_idletasks()
self.apply()
self.cancel()
def cancel(self, event=None):
# put focus back to the parent window
self.parent.focus_set()
self.destroy()
(整个事情可以在 tkSimpleDialog
文件中找到,该文件链接在我上面链接的另一个SO页面中 . )
在逐行注释掉行后,我发现 PopUpAlert
上的"ok"按钮仅在日历上没有调用 self.root.destroy()
时才起作用 . 为什么?我该如何解决?
我已经尝试将我的_19104改为 Toplevel
窗口,这也没有用 .
1 回答
提供一个mcve而不是要求我们制作它会更好 .
问题是默认情况下对话框会禁用其他窗口的点击,包括它产生的窗口 . 要解决此问题,您需要使用
Toplevel
而不是Tk
(如上所述) AND 将此行代码添加到PopUpAlert.__init__
的末尾:如果你将Toplevel子类化而不是那个奇怪的包装器,那将会更加整洁 . 这是一个mcve:
注意我也摆脱了那个无用的lambda,这恰好是我的宠儿 .
lambda
在某些情况下很棒,但很少需要它 .