我有一个小模块,当 Entry
小部件获得焦点时会弹出一个 Toplevel
小部件 . Toplevel窗口是一个键盘,因此它需要按钮单击触发一个方法,该方法将该按钮单击插入Entry小部件 . 应该在两个条件下销毁Toplevel: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小部件,或者我是从错误的方式处理这个问题,还是什么?任何帮助表示赞赏 .
EDIT :我发现了一种似乎有效的创可贴式解决方案,但我觉得还没有发现's still a better way to handle this that I haven' .
这是我添加到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
我正在添加赏金,因为我想看看是否还有另一种更清洁的方法 . 我想要的步骤是:
-
焦点移动到Entry小部件
-
创建了一个弹出式Toplevel(这是一个键盘)
-
当a)从实际键盘发生按键事件时,Toplevel被破坏,b)焦点移出Entry小部件到另一个小部件或GUI外,c)主窗口被移动
-
如果焦点稍后移回Entry小部件,则此过程是可重复的
2 回答
您可以使用状态机来处理您描述的行为 . State machines在图形用户界面中实现行为非常常见 . 这是一个简短的例子,让您了解它的外观 .
首先设计fsm,这是一个简单的几乎执行你想要的东西(为了简洁起见,跳过配置部分) .
对于实现,您可以选择一个现有的库,构建自己的框架,或者寻找一个好的旧嵌套if . 遵循我的快速和肮脏的实施 .
调整订阅以创建状态并将事件重定向到fsm:
选择要解决的状态/事件组合并执行适当的操作 . 您可能会发现您陷入某种状态并相应地调整您的FSM .
这可能会帮到你:Making a tkinter widget take focus
如果您决定只改变焦点,那么您可以将其写入以实现这一目标 .
我可能不完全理解你正在做的事情的范围,我相信它可能行为奇怪的原因是由于你对顶级的约束 .
使用:
不确定这是否有帮助,但可能会考虑添加一些:
对每种方法来说,当你切换焦点时,看看究竟发生了什么,可能有助于确定发生了什么 .