问题
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