我正在this帖子中为我的程序使用这些日历模块,并对导入进行了一些小的修改以使其适用于最新的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
的“确定”按钮(应该会破坏该窗口)停止工作:
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
日历上有一个“确定”按钮,用于确认日期的选择并关闭日历窗口。我要尝试做的是,如果用户未选择日期,则无法单击“确定”以关闭窗口。为此,我使用了validate
函数,该函数在我的tkSimpleDialog.Dialog
继承的类CalendarDialog
中预定义。我改写了CalendarDialog
类中的函数以调用PopUpAlert
,然后将False
返回给父函数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()
(整个内容可以在我上面链接的另一个SO页面中链接的tkSimpleDialog
文件中找到。)
在逐行注释之后,我发现PopUpAlert
上的“确定”按钮仅在日历上未调用self.root.destroy()
时才起作用。为什么?我该如何解决?
我已经尝试将自己的PopUpAlert
更改为Toplevel
窗口,这也无法正常工作。
答案 0 :(得分:0)
提供mcve而不是要求我们这样做会更好。
问题是默认情况下,对话框会禁用对其他窗口(包括其产生的窗口)的点击。要解决此问题,您需要使用Toplevel
而不是Tk
(如上所述) AND ,并将此行代码添加到PopUpAlert.__init__
的末尾:
self.root.grab_set()
如果您将Toplevel子类化,而不是使用那个奇怪的包装器,那将更加整洁。这是mcve:
try:
import Tkinter as tk
import tkSimpleDialog as sd
except:
import tkinter as tk
from tkinter import simpledialog as sd
#class for pop-up windows for alerts, errors etc.
class PopUpAlert(tk.Toplevel):
def __init__(self, master, alert='Alert!', **kwargs):
tk.Toplevel.__init__(self, master, **kwargs)
tk.Label(self,
text=alert,
font="Verdana 15",
fg='red',
padx=10,
pady=5).pack(side=tk.TOP)
self.bind('<Return>', self.ok)
tk.Button(self,
text='ok',
pady=10,
command=self.ok).pack(side=tk.TOP)
self.grab_set() # this window only gets commands
def ok(self, *args):
print('ok clicked')
self.destroy()
class CalendarDialog(sd.Dialog):
"""Dialog box that displays a calendar and returns the selected date"""
def body(self, master):
self.calendar = tk.Label(master, text="Whatever you do, don't click 'OK'!")
self.calendar.pack()
def validate(self):
PopUpAlert(self, alert='Please select a date or click cancel!')
def display():
CalendarDialog(root)
root = tk.Tk()
tk.Button(root, text='data data data', command=display).pack()
root.mainloop()
请注意,我还摆脱了无用的lambda,它恰好是我的宠儿。 lambda
在某些情况下很好,但是很少需要它。