【发布时间】:2014-04-06 13:52:06
【问题描述】:
我有一个小模块,当 Entry 小部件获得焦点时,它会弹出一个 Toplevel 小部件。 Toplevel 窗口是一个键盘,因此它期望按钮单击会触发一个方法,该方法将该按钮单击插入到 Entry 小部件中。 Toplevel 应该在 2 个条件下被销毁:1)用户在他们的实际键盘上按下一个键,2)Entry 小部件的父级被移动或调整大小。
一切正常,除了一个错误:如果用户单击 Toplevel,它会变为活动状态,如果发生破坏事件之一,我会得到意想不到的结果(例如当条目再次获得焦点时弹出窗口又回来了)。
我的想法是,如果我能让 Entry 在整个过程中保持焦点,一切都会正常进行,但我还没有找到实现这一目标的方法。
这是一个示例,它在保留模块结构的同时尽可能精简。注意:Python 2.7
from Tkinter import *
class Top(Toplevel):
def __init__(self, attach):
Toplevel.__init__(self)
self.attach = attach
Button(self, text='Button A', command=self.callback).pack()
self.bind('<Key>', self.destroyPopup)
def callback(self):
self.attach.insert(END, 'A')
def destroyPopup(self, event):
self.destroy()
class EntryBox(Frame):
def __init__(self, parent, *args, **kwargs):
Frame.__init__(self, parent)
self.parent = parent
self.entry = Entry(self, *args, **kwargs)
self.entry.pack()
self.entry.bind('<FocusIn>', self.createPopup)
self.entry.bind('<Key>', self.destroyPopup)
self.parent.bind('<Configure>', self.destroyPopup)
def createPopup(self, event):
self.top = Top(self.entry)
def destroyPopup(self, event):
try:
self.top.destroy()
except AttributeError:
pass
root = Tk()
e1 = EntryBox(root).pack()
root.mainloop()
那么,是否有某种never_get_focus() 方法我还没有发现我可以应用于Toplevel 小部件,或者我是从错误的方式解决这个问题,还是什么?任何帮助表示赞赏。
编辑:我找到了一种似乎有效的创可贴式解决方案,但我觉得还有更好的方法来处理这个我还没有找到。
这是我添加到 Frame 子类弹出方法中的内容:
def createPopup(self, event):
try: #When focus moves in to the entry widget,
self.top.destroy() #try to destroy the Toplevel
del self.top #and remove the reference to it
except AttributeError: #unless it doesn't exist,
self.top = Top(self.entry) #then, create it
def destroyPopup(self, event):
try:
self.top.destroy()
del self.top
except AttributeError:
pass
我正在添加赏金,因为我想看看是否有另一种更清洁的方式来做到这一点。我想要的步骤是:
- 焦点移至条目小部件
- 创建了一个弹出 Toplevel(这是一个键盘)
- 当 a) 从实际键盘发生按键事件,b) 焦点从 Entry 小部件移到另一个小部件或离开 GUI,c) 移动主窗口时,Toplevel 被破坏
- 如果焦点稍后移回 Entry 小部件,则此过程是可重复的
【问题讨论】: