防止tkinter条目在其关联的StringVar更改时获得焦点

时间:2016-03-03 15:28:51

标签: python tkinter

我有一个带有validate命令的tkinter条目,当条目获得焦点时执行(" focusin")。此条目与StringVar相关联。似乎每当StringVar更改值时,Entry都会获得焦点,从而触发验证命令。例如:

import Tkinter as tk

window = tk.Tk()
var = tk.StringVar()
def validate(*args):
    print("Validation took place")
    return True
entry = tk.Entry(validate="focusin", validatecommand=validate)
print("Entry created. Associating textvariable")
entry.config(textvariable=var)
print("textvariable associated. Changing value")
var.set("Text")
print("Value changed")
entry.pack()
tk.mainloop()

此代码生成以下输出:

Entry created. Associating textvariable
textvariable associated. Changing value
Validation took place
Value changed

请注意,执行验证命令是由对var.set的调用引起的。 有没有办法让我更改StringVar的值而不会导致其关联的Entry获得焦点?我无法暂时将StringVar与Entry取消关联,因为在重新关联它们时,Entry也会获得焦点。

2 个答案:

答案 0 :(得分:1)

一种可能的解决方法是在设置stringvar之前禁用验证事件,然后重新启用它。

(?!...)
Matches if ... doesn’t match next. This is a negative lookahead assertion. For example, Isaac (?!Asimov) will match 'Isaac ' only if it’s not followed by 'Asimov'.

(?<!...)
Matches if the current position in the string is not preceded by a match for .... This is called a negative lookbehind assertion. Similar to positive lookbehind assertions, the contained pattern must only match strings of some fixed length and shouldn’t contain group references. Patterns which start with negative lookbehind assertions may match at the beginning of the string being searched.

如果您希望这么做,您甚至可以编写一个上下文管理器,这样您就不会在完成文本更改后不小心忘记重新启用验证。

import Tkinter as tk

window = tk.Tk()
var = tk.StringVar()
def validate(*args):
    print("Validation took place")
    return True
entry = tk.Entry(validate="focusin", validatecommand=validate)
print("Entry created. Associating textvariable")
entry.config(textvariable=var)
print("textvariable associated. Changing value")
entry.config(validate="none")
var.set("Text")
entry.config(validate="focusin")
print("Value changed")
entry.pack()
tk.mainloop()

答案 1 :(得分:1)

我认为您的观察结果不正确:当您设置StringVar的值时,焦点不会改变。这可能只是在您的应用程序首次启动时才会发生的边缘情况。小部件在最初创建时可能会获得焦点。 GUI启动并运行后,设置变量不会改变焦点。

official tk documentation不鼓励使用验证和使用变量。来自文档:

  

通常,textVariable和validateCommand混合可能很危险。已经克服了任何问题,因此使用validateCommand不会干扰条目小部件的传统行为。

在这种情况下,没有理由使用StringVar。我的建议是删除它。使用StringVar通常只有在多个窗口小部件使用相同的变量或者对变量进行跟踪时才有用。你没有这样做,所以只是停止使用StringVar。它增加了一个额外的对象来管理而不提供额外的好处。

相关问题