Tkinter validatecommand 命令破坏参数类型?

Tkinter validatecommand command mangles argument type?

我一直在尝试在 Entry 小部件中进行一些类型检查,方法是附加一个处理函数,该函数提供了条目和预期类型(来自内置的 Type class 对象)类型()函数)。除了 validatecommand 似乎将 Type 对象的类型从 Type 更改为字符串外,一切正常,这并非无法克服,但让我很好奇发生了什么。

请参阅下面的最小可重现示例 - 请注意处理程序已正确传递原生类型对象 python,但使用 tkinter 时类型对象的类型更改为字符串。

#NATIVE PYTHON

variable = 'HelloWorld'
vartype = type(variable)

print('VALUE OF VARTYPE: ', vartype, 'TYPE OF VARTYPE: ', type(vartype))

def handler(variable,vartype):
    print('VALUE OF VARTYPE: ', vartype, 'TYPE OF VARTYPE: ', type(vartype))

handler(variable,vartype)

#TKINTER VALIDATE HANDLER

import tkinter as tk

top = tk.Tk()
frame = tk.Frame(top)
frame.pack()
vcmd =frame.register(handler)
entry = tk.Entry(frame, validate = 'focusout', validatecommand = (vcmd,"%P",vartype))
entry.pack()

top.mainloop()

解决这个问题的方法是为处理程序制作一个 lambda 包装器,避免将类型对象传递给 validatecommand:


#NATIVE PYTHON

variable = 'HelloWorld'
vartype = type(variable)


print('VALUE OF VARTYPE: ', vartype, 'TYPE OF VARTYPE: ', type(vartype))

def handler(*variable,vartype=vartype):
    print('VALUE OF VARTYPE: ', vartype, 'TYPE OF VARTYPE: ', type(vartype))

handler(*variable,vartype=vartype)

#TKINTER VALIDATE HANDLER

import tkinter as tk

top = tk.Tk()
frame = tk.Frame(top)
frame.pack()
vcmd =frame.register(lambda *args, vartype=vartype : handler(*args,vartype=vartype))
entry = tk.Entry(frame, validate = 'focusout', validatecommand = (vcmd,"%P"))
entry.pack()

top.mainloop()

然而,我仍然有些不满意不知道第一次迭代发生了什么 - 我在那里做错了什么?

All works well except it appears the validatecommand changes the type of the Type object from Type to a string, which is not insurmountable but has made me curious what's going on.... However, I have still somewhat unsatisfied not knowing what happened with the first iteration - what am I doing wrong there?

你没有做错任何事,只是试图做一些 tkinter 设计上不支持的事情。

Tkinter 是一个围绕嵌入式 Tcl 解释器的面向对象的包装器。这个嵌入式解释器对 python 对象一无所知,因此 python 对象不能传递到 Tcl 解释器或从中检索。当您将 python 函数作为参数传递时,tkinter 必须先将其转换为字符串,然后才能由 Tcl 解释器处理。

这就是您必须向 Tcl 解释器注册 python 函数的原因。 Tkinter 将创建一个知道如何调用 python 函数的内部 Tcl 函数。然后可以在 Tcl 解释器内部使用此函数的名称。