how do I create entry fields and buttons to get the content from the entry field using iteration in tkinter for python?

为君一笑 提交于 2021-01-29 11:22:12

问题


I'm trying to make a tkinter GUI with a certain amount of buttons and entry fields that is specified by the user, so in this code below for example if the user specifies the variable number to be 3 I want there to be 3 entry boxes and , and I want to set it up so that if I type a value into the first field and click the button next to it, I want that button to read the value from the entry field next to it. I also need to assign each entry field to a variable that will be created through the same iterative loop. However, I'm having difficulty especially in regards to mapping the buttons to the entry fields, as I always seem to run up against an error with the text "AttributeError: 'NoneType' object has no attribute 'get'". Would anyone be able to either fix my code or help me find an alternative solution to the problem? Sorry if the description's a bit confusing. This is different from just a problem of just getting the contents of the entry widget as I need it to create a certain amount of entry widgets and buttons using iteration, and the question that my question has been marked a duplicate of doesn't explain how to iteratively map each entry field to each button. For example, if I enter 3 as the variable, I need the program to create entry field 1, entry field 2 and entry field 3 and button 1, button 2 and button 3 and then map each button to its respective entry field using iteration. I've tried using dictionaries, but this doesn't seem to help much.

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)

回答1:


You need to save the Entry and Button before calling grid:

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()

This should help you get started.

In your comment, you ask how to save the value in the Entry. I would create a class to handle everything:

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}")

As you can see, this eliminates a lot of extra work.




回答2:


The solution to "'NoneType' object has no attribute 'get'" has been asked probably a hundred times on this site, and the answer is always the same.

In python, when you do x = y().z(), x will be given the value of z(). In the case of x=tk.Entry(...).grid(...), x will be None because grid(...) always returns None. The solution is to always call grid or pack or place separate from when you create a widget.

You also claim you are having problems with dictionaries, but I don't see any problem in your code other than you are making it more difficult than necessary. You can directly use i as an index without having to build up a string for the index. If you need to keep track of both buttons and entries, I recommend two variables rather than one.

Part of the problem may also have to do with the fact you're trying to do something very odd in your command. You're trying to call the get method of the entry, but that's pointless since it simply returns a value that gets thrown away. In almost all cases, the correct solution is to write a proper function rather than trying to squeeze functionality into a lambda.

Example:

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)



回答3:


For get text from entry

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

More info



来源:https://stackoverflow.com/questions/57378323/how-do-i-create-entry-fields-and-buttons-to-get-the-content-from-the-entry-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!