[英]Getting the textvariable out of a Tkinter Entry widget?
我正在尝试将一个函数绑定到我的 Tkinter 根目录,该根目录会在用户按下返回时做出反应。 这是代码:
def returnPressed(event):
print repr(event.widget)
master = Tk()
master.bind("<Return>", returnPressed)
myStringVar = StringVar(value="Foo")
myEntry = Entry(master, textvariable=myStringVar)
myEntry.grid()
master.mainloop()
这可行,但是现在我需要在returnPressed
函数中获取Entry
的StringVar
变量。
我有小部件,但我无法获取变量对象。 我知道如何获取变量内容,但我真的需要对象。
要获取小部件的任何属性,请使用cget
:
print(event.widget.cget("textvariable"))
但是,在此特定实例中,由于某些实现细节,您返回的是 stringvar 的内部名称而不是 stringvar 本身。 所以,你必须找到另一种方式。
最简单的方法可能是将 stringvar 实例传递给被调用的函数。 您可以使用 lambda 或 functools.partial 执行此操作。 例如:
def returnPressed(event, v):
...
master.bind("<Return>",lambda event, v=myStringVar: returnPressed(event, v))
我通过使用包含对Entry
和它使用的StringVar
文本变量的引用的外部对象来解决 tkinter 在这方面的糟糕设计,以便于访问( tuple
也可以工作):
class EntryWithText()
def __init__(self):
self.entry = None
self.textvariable = StringVar() #or None
entryWithTexts = []
for i in range(10):
entryWithTexts[i] = EntryWithText()
entryWithTexts[i].entry = Entry(master, textvariable=entryWithTexts[i].textvariable, ...)
entryWithTexts[i].textvariable.set("this is entry number " + str(i))
毫无疑问,如果您有 10 万个这样的条目,额外的间接级别会产生一些影响,但我在这里编写了一些小实用程序,所以不用担心。
以为我会继续说我发现了一种方法。
读取小部件的 'textvariable' 选项值会为您提供先前设置的变量的名称。 使用此名称初始化 StringVar 实例将为您提供一个似乎链接到原始实例的新实例。 没有值的初始化会保留当前值。 我说“链接”是因为新实例和原始实例不是同一个对象(由它们的 id 验证),但是在新实例上设置值将更改小部件中对象中的值。 请参阅 Variable._ init _ 的文档。
name = event.widget['textvariable']
var = StringVar(root, name=name)
我知道这是一个老问题,但我想我通过内部化控制变量找到了解决 tkinter 限制的方法。 然后,您无需在创建小部件时声明单独的值:
class DynamicLabel(tkinter.Label):
def __init__(self, master, *args, **kwargs):
super().__init__(master=master, *args, **kwargs)
self.master = master
self.value=None
for kwarg, value in kwargs.items():
if kwarg == 'textvariable':
if not isinstance(value, tkinter.StringVar):
raise ValueError('Textvariable must be StringVar')
self.value = value
if not self.value:
self.value = tkinter.StringVar()
self.config(textvariable=self.value)
def set(self, txt):
self.value.set(txt)
def get(self):
return self.value.get()
这样做是用self.value
为控制变量创建一个代理。
然后我们将遍历所有 kwargs,如果找到textvariable
,我们将self.value
的引用。
如果在创建小部件时没有设置 textvariable,我们只需创建自己的并使用self.config(textvariable=self.value)
将其分配给小部件
剩下的就是创建 set 和 get 方法来访问控制变量。
我想通过忽略在创建小部件时分配的任何textvariable
并始终从头开始创建一个新的,可以进一步简化上述内容。
你甚至可以让self.value
成为一个属性,以便能够直接与self.value
交互
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.