【问题标题】:how do I create entry fields and buttons to get the content from the entry field using iteration in tkinter for python?如何使用 tkinter for python 中的迭代创建输入字段和按钮以从输入字段中获取内容?
【发布时间】:2019-08-06 14:27:40
【问题描述】:

我正在尝试制作一个 tkinter GUI,其中包含用户指定的一定数量的按钮和输入字段,因此在下面的代码中,例如,如果用户将变量编号指定为 3,我希望有3 个输入框和 , 我想设置它,以便如果我在第一个字段中输入一个值并单击它旁边的按钮,我希望该按钮从它旁边的输入字段中读取值。我还需要将每个输入字段分配给将通过相同的迭代循环创建的变量。但是,我在将按钮映射到输入字段方面遇到了困难,因为我似乎总是遇到文本“AttributeError:'NoneType'对象没有属性'get'”的错误。任何人都可以修复我的代码或帮助我找到问题的替代解决方案吗?抱歉,如果描述有点混乱。 这与仅获取条目小部件内容的问题不同,因为我需要它来使用迭代创建一定数量的条目小部件和按钮,而我的问题已被标记为重复的问题并没有解释如何迭代地将每个输入字段映射到每个按钮。例如,如果我输入 3 作为变量,我需要程序创建输入字段 1、输入字段 2 和输入字段 3 以及按钮 1、按钮 2 和按钮 3,然后使用迭代将每个按钮映射到其各自的输入字段。 我尝试过使用字典,但这似乎没有多大帮助。

import tkinter as tk
root = tk.Tk()
number = 3
d={}
def callBack():
    print(d["E{0}".format(i)].get())
    return
for i in range(0,number):
    d["E{0}".format(i)] = tk.Entry(root)
    d["E{0}".format(i)].grid(row=i, column=0)
    d["B{0}".format(i)] = tk.Button(root, text="test", command=callBack)
    d["B{0}".format(i)].grid(row=i, column=1)

【问题讨论】:

  • 您需要提供回调作为command 参数。在回调中,调用相关的get方法。
  • AttributeError: 'NoneType' object has no attribute 'get' - 如果您定义小部件并同时调用几何管理器方法,您将收到此信息。阅读Tkinter: AttributeError: NoneType object has no attribute <attribute name>
  • @DavidCullen 我照你说的做了,虽然我仍然有同样的错误!
  • @HenryYik 我试过了,它有所帮助,但我仍然有一个错误,无论我点击什么按钮,只打印第三个输入框中的数据。我该如何解决这个问题,所以按钮 1 打印输入框 1,按钮 2 打印输入框 2,按钮 3 打印输入框 3?

标签: python user-interface tkinter iteration tkinter-entry


【解决方案1】:

“'NoneType'对象没有属性'get'”的解决方案在这个网站上被问了大概一百次,答案总是一样的。

在python中,当你执行x = y().z()时,x将被赋予z()的值。对于x=tk.Entry(...).grid(...)x 将是None,因为grid(...) 总是返回None。解决方案是始终调用gridpackplace,与创建小部件时分开。

您还声称您在使用字典时遇到了问题,但我在您的代码中没有发现任何问题,只是您让代码变得比必要的更困难。您可以直接使用i 作为索引,而无需为索引构建字符串。如果您需要同时跟踪按钮和条目,我建议使用两个变量而不是一个。

部分问题也可能与您在command 中尝试做一些非常奇怪的事情有关。您正在尝试调用条目的 get 方法,但这毫无意义,因为它只是返回一个被丢弃的值。在几乎所有情况下,正确的解决方案是编写适当的函数,而不是试图将功能压缩到 lambda 中。

例子:

def handle_click(i):
    entry = entries[i]
    print("the value is {}".format(entry.get()))

buttons = {}
entries = {}
for i in range(0,number):
    entry = tk.Entry(root)
    button = tk.Button(root, text="test", command=lambda i=i: handle_click(i))

    buttons[i] = button
    entries[i] = entry

    entry.grid(row=i, column=0)
    button.grid(row=i, column=1)

【讨论】:

    【解决方案2】:

    在调用grid之前需要保存EntryButton

    import tkinter as tk
    
    number = 3
    root = tk.Tk()
    
    def get_on_click(widget_dict, entry_name):
        def on_click():
            result = widget_dict[entry_name].get()
            print("%s = %s" % (entry_name, result))
            return result
        return on_click
    
    d = dict()
    for i in range(0, number):
        entry_name = "E{0}".format(i)
        button_name = "B{0}".format(i)
        print(entry_name, button_name)
        d[entry_name] = tk.Entry(root)
        d[entry_name].grid(row=i, column=0)
        d[button_name] = tk.Button(root, text="test", command=get_on_click(d, entry_name))
        d[button_name].grid(row=i, column=1)
    
    root.mainloop()
    

    这应该可以帮助您入门。

    在您的评论中,您询问如何保存Entry 中的值。我会创建一个类来处理所有事情:

    import tkinter as tk
    
    number = 3
    root = tk.Tk()
    
    class EntryButton(object):
        def __init__(self, root, number):
            self.number = number
            self.entry = tk.Entry(root)
            self.button = tk.Button(root, text="test", command=self.on_click)
            self.entry.grid(row=number, column=0)
            self.button.grid(row=number, column=1)
            self.value = None
    
        def on_click(self):
            self.value = self.entry.get()
    
    storage = dict()
    for i in range(0, number):
        storage[i] = EntryButton(root, i)
    
    root.mainloop()
    
    for i in range(0, number):
        value = storage[i].value
        print(f"storage[{i}] = {value}")
    

    如您所见,这消除了很多额外的工作。

    【讨论】:

    • 非常感谢,这对我来说帮助很大,而且很容易理解。知道如何通过迭代将输入字段数据分配给变量,例如,如果输入字段 1 中包含数据“土豆”,那么我将如何将该数据分配给通过迭代生成的名为 variable1 的变量所以那个 variable1 = "potatoes" 和输入字段 2 和 variable2 一样吗?
    • 我会创建一个类并用它来处理所有的工作。请参阅我的更新答案。
    【解决方案3】:

    用于从条目中获取文本

    Entry.get("1.0", "end-1c")
    # 1.0 for get first line.
    # end-1c for if last letter space, this deletes it.
    

    More info

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-16
      • 2011-12-11
      • 2013-03-23
      • 2011-01-25
      • 1970-01-01
      • 2020-02-12
      • 2022-01-08
      相关资源
      最近更新 更多