【问题标题】:Getting the textvariable out of a Tkinter Entry widget?从 Tkinter 条目小部件中获取文本变量?
【发布时间】:2013-01-15 17:37:16
【问题描述】:

我正在尝试将一个函数绑定到我的 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 函数中获取EntryStringVar 变量。

我有小部件,但我无法获取变量对象。我知道如何获取变量内容,但我确实需要对象。

【问题讨论】:

  • 或许可以试试master.bind("&lt;Return&gt;",lambda: returnPressed(myStringVar))
  • 为什么需要这个对象?以我的经验,除非您打算对变量进行跟踪,否则几乎不需要 StringVars,而您没有这样做。也许你工作太努力了,无法完成任务。
  • 我同意布莱恩的观点。查看his other answer ;-]
  • 您可能还可以从研究this answer 的第一个示例中受益。它展示了如何检索条目的内容并将其存储为类属性的值。

标签: python tkinter tkinter-entry


【解决方案1】:

要获取小部件的任何属性,请使用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))

【讨论】:

  • 这里的repr() 是做什么的?
  • @CoolCloud:没什么用。我不知道我为什么在将近 9 年前写了这篇文章。
【解决方案2】:

我通过使用包含对 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 万个这样的条目,额外的间接级别会产生一些影响,但我在这里写的是小型实用程序,所以不用担心。

【讨论】:

    【解决方案3】:

    我想我已经找到了一种方法。

    读取小部件的“textvariable”选项值会为您提供先前设置的变量名称。使用此名称初始化 StringVar 实例将为您提供一个似乎链接到原始实例的新实例。 没有值的初始化会保留当前值。我说“链接”是因为新实例和原始实例不是同一个对象(由它们的 id 验证),但是在新实例上设置值将更改小部件中对象中的值。请参阅变量的文档。_init_。

        name = event.widget['textvariable']
        var = StringVar(root, name=name)
    

    【讨论】:

      【解决方案4】:

      我知道这是一个老问题,但我认为我通过内部化控制变量找到了解决 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 引用它。

      如果创建小部件时没有设置文本变量,我们只需创建自己的并将其分配给带有self.config(textvariable=self.value)的小部件

      剩下的就是创建 set 和 get 方法来访问控制变量。

      我想通过忽略创建小部件时分配的textvariable 并始终从头开始创建一个新的,可以进一步简化上述内容。

      您甚至可以将self.value 设为property 以便能够直接与self.value 交互

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多