Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何确保我的ttk.Entry';s的无效状态为';当它失去焦点时,它不会被清除吗?_Python_Validation_Tkinter_Ttk - Fatal编程技术网

Python 如何确保我的ttk.Entry';s的无效状态为';当它失去焦点时,它不会被清除吗?

Python 如何确保我的ttk.Entry';s的无效状态为';当它失去焦点时,它不会被清除吗?,python,validation,tkinter,ttk,Python,Validation,Tkinter,Ttk,每当内容更改时,我想设置或清除ttk.Entry的invalid状态标志。为此,我将StringVar连接到条目,并在trace()回调中调用state(['valid'])或state(['!invalid'])。我的回调正确设置了该标志,但是,每当焦点离开文本条目时,它就会被清除!我如何避免或解决这个问题 我想设置或清除标志,因为我可以根据州标志更改视觉样式。我不想禁止用户输入任何无效的内容;我希望他们可以自由地键入他们想要的任何内容,并立即查看它是否有效。我想特别使用invalid标志,而

每当内容更改时,我想设置或清除
ttk.Entry
invalid
状态标志。为此,我将
StringVar
连接到条目,并在
trace()
回调中调用
state(['valid'])
state(['!invalid'])
。我的回调正确设置了该标志,但是,每当焦点离开文本条目时,它就会被清除!我如何避免或解决这个问题

我想设置或清除标志,因为我可以根据州标志更改视觉样式。我不想禁止用户输入任何无效的内容;我希望他们可以自由地键入他们想要的任何内容,并立即查看它是否有效。我想特别使用
invalid
标志,而不是
alternate
标志,这不仅是因为
invalid
是更合乎逻辑的选择,也是因为我已经在为其他事情使用
alternate
标志

我没有使用此小部件的内置验证功能,因为根据,如果我在编辑文本时调用验证命令(
-validate
等于
'keys'
'all'

条目将在每次编辑之前预先验证。。。如果预验证失败,则拒绝编辑

就像我之前说的,我不想那样。我想知道
-validate
等于
'none'
应该做什么:

只有当
validate
widget命令特别请求时,才会进行验证

很好,所以理论上我所要做的就是永远不要调用
validate()
。不幸的是,
无效
标志仍被清除。我可以在Python的交互模式中重现这种意外和不需要的行为:

>>> import tkinter as tk
>>> from tkinter import ttk
>>> win = tk.Tk()
>>> entry = ttk.Entry(win)
>>> entry.pack()
>>> entry['validate']
'none'
>>> entry.state()
()
>>> entry.state(['invalid'])
('!invalid',)
>>> entry.state()
('invalid',)
到目前为止,一切顺利。(在本例中,我使用的是Python 3,但使用Python 2得到的结果相同。)现在,我将焦点切换到输入框和从输入框切换到:

>>> entry.state()
()
-validate
'none'
,而不是
'focus'
'all'
时,它为什么会被清除?我能做些什么来使用
无效的
状态吗


我在Linux上使用Tcl/Tk版本8.6的Python 3.4.2和2.7.9中看到了相同的行为。

这里是解决问题的方法。您可能想根据自己的需要调整它,但它可能会给您一个想法:

import tkinter as tk
from tkinter import ttk

class ValidatingEntry(ttk.Entry):

    COLOR_VALID = "#99ff99"
    COLOR_INVALID="#ff9999"

    def __init__(self, master, *args, **kwargs):
        self.stringVar = tk.StringVar()

        tk.Entry.__init__(self, master, *args, textvariable = self.stringVar, **kwargs)

        self.validatingFunction = None

        self.bind("<FocusOut>",self.validation)

    def validation(self, event):

        if self.validatingFunction != None:
            if self.validatingFunction():
                self['bg']=ValidatingEntry.COLOR_VALID
            else:
                self['bg']=ValidatingEntry.COLOR_INVALID
        else:
            print("no evaluation possible for the content of this entry")


if __name__ == "__main__":
    app = tk.Tk()

    entry = ValidatingEntry(app)
    entry.validatingFunction = lambda : 'foo' in entry.stringVar.get()
    entry.pack()

    entry2 = ValidatingEntry(app)
    entry2.validatingFunction = lambda : 'bar' in entry2.stringVar.get()
    entry2.pack()


    app.mainloop()
将tkinter作为tk导入
从tkinter导入ttk
类ValidatingEntry(ttk.Entry):
COLOR_VALID=“#99ff99”
COLOR_INVALID=“#ff9999”
定义初始值(self、master、*args、**kwargs):
self.stringVar=tk.stringVar()
tk.Entry.\uuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
self.validatingFunction=None
self.bind(“,self.validation)
def验证(自身、事件):
如果self.validatingFunction!=无:
如果self.validatingFunction():
self['bg']=ValidatingEntry.COLOR\u有效
其他:
self['bg']=ValidatingEntry.COLOR\u无效
其他:
打印(“不可能对该条目的内容进行评估”)
如果名称=“\uuuuu main\uuuuuuuu”:
app=tk.tk()
entry=ValidatingEntry(应用程序)
entry.validatingFunction=lambda:entry.stringVar.get()中的“foo”
entry.pack()
entry2=ValidatingEntry(应用程序)
entry2.validatingFunction=lambda:entry2.stringVar.get()中的“bar”
entry2.pack()
app.mainloop()
例如,可以修改类以获取模式参数,并使用它检查StringVar内容是否与regexp模式匹配。但这与传统知识无关

希望能有帮助。
Arthur.

将您自己的绑定添加到
,该绑定将调用验证函数并重置状态

下面是一个完整的工作示例。如果条目小部件包含单词“invalid”,则状态将更改为“invalid”。然后,您可以从小部件中单击以查看状态是否仍然无效:

try:
    import Tkinter as tk
    import ttk
except ImportError:
    import tkinter as tk
    from tkinter import ttk

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        # give invalid entries a red background
        style = ttk.Style()
        style.map("TEntry",  background=[('invalid', "red")])

        self.entryVar = tk.StringVar()
        self.entry = ttk.Entry(self, textvariable=self.entryVar)

        # this label will show the current state, updated 
        # every second.
        self.label = tk.Label(self, anchor="w")
        self.after_idle(self.updateLabel)

        # layout the widgets
        self.entry.pack(side="top", fill="x")
        self.label.pack(side="bottom", fill="x")

        # add trace on the variable to do custom validation
        self.entryVar.trace("w", self.validate)

        # set up bindings to also do the validation when we gain
        # or lose focus
        self.entry.bind("<FocusIn>", self.validate)
        self.entry.bind("<FocusOut>", self.validate)

    def updateLabel(self):
        '''Display the current entry widget state'''
        state = str(self.entry.state())
        self.label.configure(text=state)
        self.after(1000, self.updateLabel)

    def validate(self, *args):
        '''Validate the widget contents'''
        value = self.entryVar.get()
        if "invalid" in value:
            self.entry.state(["invalid"])
        else:
            self.entry.state(["!invalid"])

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()
试试看:
将Tkinter作为tk导入
导入ttk
除恐怖外:
将tkinter作为tk导入
从tkinter导入ttk
类示例(tk.Frame):
定义初始化(自身,父级):
tk.Frame.\uuuu init\uuuuu(自,父)
#为无效条目提供红色背景
style=ttk.style()
map(“TEntry”,background=[(“无效”,“红色”)]))
self.entryVar=tk.StringVar()
self.entry=ttk.entry(self,textvariable=self.entryVar)
#此标签将显示当前状态(已更新)
#每一秒。
self.label=tk.label(self,anchor=“w”)
空闲后的self.after(self.updateLabel)
#布局小部件
自进式包装(side=“top”,fill=“x”)
自贴标签包装(side=“bottom”,fill=“x”)
#在变量上添加跟踪以进行自定义验证
self.entryVar.trace(“w”,self.validate)
#设置绑定,以便在获得
#或者失去焦点
self.entry.bind(“,self.validate)
self.entry.bind(“,self.validate)
def updateLabel(自):
''显示当前条目小部件状态''
state=str(self.entry.state())
self.label.configure(文本=状态)
self.after(1000,self.updateLabel)
def验证(自身,*参数):
''验证小部件内容''
value=self.entryVar.get()
如果值为“无效”:
self.entry.state([“无效”])
其他:
self.entry.state([“!invalid”])
如果名称=“\uuuuu main\uuuuuuuu”:
root=tk.tk()
示例(root).pack(fill=“both”,expand=True)
root.mainloop()
为什么会这样 在Tk源文件中,
EntryRevalidate()
总是在焦点事件上运行。这将调用
EntryValidateChange()
,当它注意到焦点事件的验证已“关闭”时,将返回一个结果,指示当前值对
EntryRevalidate()有效
class MyEntry(ttk.Entry):

    def __init__(self, master):
        self.var = tk.StringVar(master)
        super().__init__(master,
                         textvariable=self.var,
                         validate='focus',
                         validatecommand=self.is_valid)
        self.var.trace('w', self.revalidate)
        self.revalidate()

    def revalidate(self, *args):
        self.state(['!invalid' if self.is_valid()
                    else 'invalid'])

    def is_valid(self, *args):
        # ... return if current text is valid ...
class ValidationDisabledEntry(ttk.Entry):
    def __init__(self, *args, **kwargs):
        super().__init__(
            *args,
            validate='focus',
            validatecommand=lambda *a: 'invalid' not in self.state(),
            **kwargs)