python3、tkinter NoneType错误
python 3, tkinter NonType error
我读过许多关于出现 NonType
错误的帖子,因为他们试图在定义 [=] 的同一行上 .pack()
、.grid()
或 .place()
19=]变量。
例子
execute = tk.Button(text="Start", command=lambda:
Elements.ClickApp()).place(x=20, y=250, height=20, width=50)
回应是 A,不可能有 2 个函数,而且 B 很难在一行中阅读。我开始(不情愿地)接受 .pack()
、.grid()
或 .place()
的附加行,但现在遇到了附加行(甚至不起作用)。如:
T = tk.Entry()
T.bind("<Key>", Elements.Tbox)
T.place(x=20, y=230, height=20, width=50)
不仅这三行不能放在一行,这就是我想要的..但是代码甚至无法运行。相反,第一个按下的按钮会被忽略,然后第二个按钮(及以后)会触发 Elements.Tbox
.
相反,必须进一步增加换行符:
sv = tk.StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: Elements.Tbox(sv))
T = tk.Entry(textvariable=sv)
T.place(x=20, y=230, height=20, width=50)
然后在第一次按下按钮时正确触发 Elements.Tbox
。
有没有办法(也许 lambda
)可以减少这些新行? ... 在处理大量小部件时,以这种方式对小部件进行分组更容易阅读。我发现这比单独的行更具可读性。
更新
我已经在这个问题的 答案 中包含了示例代码...尽管标记为正确的答案可能是更好的建议。如果有人需要这样做或类似的事情,您可以执行以下操作:
条目小部件示例:
将 EntryBox = tk.Entry()
与 .place()
、.pack()
或 .grid()
组合
(lambda g: [(EntryBox.place(x=0, y=0, height=20, width=190)) for g['EntryBox'] in [tk.Entry()]])(globals())
如果我没理解错的话,您想将这三行减少为更少的行:
T = tk.Entry()
T.bind("<Key>", Elements.Tbox)
T.place(x=20, y=230, height=20, width=50)
简而言之,你不能。至少,不是没有让代码更难理解,这对软件开发来说是一个anti-pattern。
原因只是使用像 python 这样的动态语言进行编程的一个基本方面:您不能在对象存在之前引用它们。因此,在可以调用 pack
、place
、grid
或 bind
之前,小部件必须存在。鉴于这些函数 return None
,您不能像在其他语言中那样链接它们。
您可能想像这样组合第一个和第三个语句:
T = tk.Entry().place(x=20, y=230, height=20, width=50)
那也不行。原因是 T
将被设置为 None
,导致以后无法引用该小部件。这是因为在python、x().y()
中returns的值为y()
,因此在Entry().grid()
、grid
中总是returns `None.
根据我的经验,您永远不应将小部件创建和小部件布局命令组合在一起。相反,在一组中创建您的小部件,然后将它们布置在另一组中。绑定通常也是如此。
为什么?因为通常当您需要解决布局问题时,它涉及更改多个小部件的选项,因此将它们组合在一起很方便。
根据我的经验,当将执行类似操作的代码组合在一起而不是将与同一对象相关的所有语句组合在一起时,GUI 代码更易于阅读和管理。
例如:
x = tk.Entry(...)
y = tk.Button(...)
z = tk.Label(...)
x.grid(...)
y.grid(...)
z.grid(...)
x.bind(...)
y.bind(...)
z.bind(...)
当然,这不是硬性规定。目标应该始终是清晰的,有时将小部件的创建和布局放在一起是有意义的,尽管这通常是在您只处理一个小部件的情况下。
如果您想创建一堆参数几乎相同的相同小部件,您应该创建一个辅助函数,而不是在一行中尽可能多地塞满内容。
例如,在您的情况下,您可能想要创建一个 create_entry 函数:
def create_entry(master, x, y, width, height, callback):
entry = tk.Entry(master)
entry.bind("<Key>", callback)
entry.place(x=x, y=y, height=20, width=20)
return entry
至此,您现在拥有梦寐以求的 one-line 解决方案:
T = create_entry(root, 20, 230, 20, 50, Elements.Tbox)
U = create_entry(root, 20, 290, 20, 50, Elements.Tbox)
V = create_entry(root, 20, 290, 20, 50, Elements.Tbox)
...
我读过许多关于出现 NonType
错误的帖子,因为他们试图在定义 [=] 的同一行上 .pack()
、.grid()
或 .place()
19=]变量。
例子
execute = tk.Button(text="Start", command=lambda:
Elements.ClickApp()).place(x=20, y=250, height=20, width=50)
回应是 A,不可能有 2 个函数,而且 B 很难在一行中阅读。我开始(不情愿地)接受 .pack()
、.grid()
或 .place()
的附加行,但现在遇到了附加行(甚至不起作用)。如:
T = tk.Entry()
T.bind("<Key>", Elements.Tbox)
T.place(x=20, y=230, height=20, width=50)
不仅这三行不能放在一行,这就是我想要的..但是代码甚至无法运行。相反,第一个按下的按钮会被忽略,然后第二个按钮(及以后)会触发 Elements.Tbox
.
相反,必须进一步增加换行符:
sv = tk.StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: Elements.Tbox(sv))
T = tk.Entry(textvariable=sv)
T.place(x=20, y=230, height=20, width=50)
然后在第一次按下按钮时正确触发 Elements.Tbox
。
有没有办法(也许 lambda
)可以减少这些新行? ... 在处理大量小部件时,以这种方式对小部件进行分组更容易阅读。我发现这比单独的行更具可读性。
更新
我已经在这个问题的 答案 中包含了示例代码...尽管标记为正确的答案可能是更好的建议。如果有人需要这样做或类似的事情,您可以执行以下操作:
条目小部件示例:
将 EntryBox = tk.Entry()
与 .place()
、.pack()
或 .grid()
(lambda g: [(EntryBox.place(x=0, y=0, height=20, width=190)) for g['EntryBox'] in [tk.Entry()]])(globals())
如果我没理解错的话,您想将这三行减少为更少的行:
T = tk.Entry()
T.bind("<Key>", Elements.Tbox)
T.place(x=20, y=230, height=20, width=50)
简而言之,你不能。至少,不是没有让代码更难理解,这对软件开发来说是一个anti-pattern。
原因只是使用像 python 这样的动态语言进行编程的一个基本方面:您不能在对象存在之前引用它们。因此,在可以调用 pack
、place
、grid
或 bind
之前,小部件必须存在。鉴于这些函数 return None
,您不能像在其他语言中那样链接它们。
您可能想像这样组合第一个和第三个语句:
T = tk.Entry().place(x=20, y=230, height=20, width=50)
那也不行。原因是 T
将被设置为 None
,导致以后无法引用该小部件。这是因为在python、x().y()
中returns的值为y()
,因此在Entry().grid()
、grid
中总是returns `None.
根据我的经验,您永远不应将小部件创建和小部件布局命令组合在一起。相反,在一组中创建您的小部件,然后将它们布置在另一组中。绑定通常也是如此。
为什么?因为通常当您需要解决布局问题时,它涉及更改多个小部件的选项,因此将它们组合在一起很方便。
根据我的经验,当将执行类似操作的代码组合在一起而不是将与同一对象相关的所有语句组合在一起时,GUI 代码更易于阅读和管理。
例如:
x = tk.Entry(...)
y = tk.Button(...)
z = tk.Label(...)
x.grid(...)
y.grid(...)
z.grid(...)
x.bind(...)
y.bind(...)
z.bind(...)
当然,这不是硬性规定。目标应该始终是清晰的,有时将小部件的创建和布局放在一起是有意义的,尽管这通常是在您只处理一个小部件的情况下。
如果您想创建一堆参数几乎相同的相同小部件,您应该创建一个辅助函数,而不是在一行中尽可能多地塞满内容。
例如,在您的情况下,您可能想要创建一个 create_entry 函数:
def create_entry(master, x, y, width, height, callback):
entry = tk.Entry(master)
entry.bind("<Key>", callback)
entry.place(x=x, y=y, height=20, width=20)
return entry
至此,您现在拥有梦寐以求的 one-line 解决方案:
T = create_entry(root, 20, 230, 20, 50, Elements.Tbox)
U = create_entry(root, 20, 290, 20, 50, Elements.Tbox)
V = create_entry(root, 20, 290, 20, 50, Elements.Tbox)
...