An array of Entries was created using the following code
from tkinter import *
root = Tk()
height = 5
width = 5
delta=0
for i in range(height): #Rows
for j in range(width): #Columns
b = Entry(root, text="",width=8)
b.grid(row=i, column=j)
mainloop()
How do I access each Entry to update its value ( using StringVar - for example ) ?
You could create a list of lists for your Entry widgets.
from tkinter import *
root = Tk()
height = 5
width = 5
delta=0
entries = []
for i in range(height): #Rows
newrow = []
for j in range(width): #Columns
b = Entry(root, text="",width=8)
b.grid(row=i, column=j)
newrow.append(b)
entries.append(newrow)
mainloop()
You could then address individual entries as e.g. entries[2][4].
Edit: To edit the text of entry widget e, first use e.delete(0, END) to clear it, and then use e.insert(0, "new text") to insert new text.
Edit2: Alternatively, you could store the StringVars in a list of lists instead of the widgets...
You need to first declare the StringVar variable:
myvar = StringVar()
Then in your loop whenever you want to check to content of the variable use the get() method.
x = myvar.get()
Now x will hold the value. You can also perform a bool test with if
if myvar.get():
print(myvar.get())
In that if statement the program checks if there is data in the var. If not it will move on
Looking at it again you should also declare the StringVar() in your button. Like so:
b = Button(text='clickme', texvariable=myvar)
Look Here for more info
Related
I am working on a project that solves sudoku puzzles. To gather the inputs I am using a GUI called "Tkinter" with 81 separate input(entry) boxes. I also have a submit button. When I press submit I would like to create a series of objects that contain atribues like cell value, row, and column. the code below does this, but I would have to copy and paste this code 81 times only adjusting the variable names and position by one each time(within the submit function). Is there any way to create a loop that could iterate these lines of code 81 times while altering the number part of the variable names?
class Cell:
def __init__(self,number,location):
self.number = number
self.row = (location // 9) + 1
self.column = (location % 9) + 1
def submit():
cell1 = Cell(c1.get(),0)
cell2 = Cell(c2.get(),1)
cell3 = Cell(c3.get(),2)
...
*the .get() method is how I am retrieving the numbers from the input boxes(called c1,c2,c3...) once the button is pressed.
**location is just a number(0-80) that I use to find the row and column info.
The simplest I could think of was to use nested for loops to create the widgets and grid them (btw row and column start at 0) and append to a list, from where they can be later referenced. So when you press the button, it goes over each of the Entrys in that list and calls their get method (and prints the value):
import tkinter as tk
def submit():
for e in entry_list:
print(e.get())
root = tk.Tk()
entry_list = []
for col in range(9):
for row in range(9):
entry = tk.Entry(root, width=2, font=('Calibri', 20))
entry.grid(row=row, column=col, sticky='news')
entry_list.append(entry)
btn = tk.Button(root, text='Submit', command=submit)
btn.grid(row=9, column=0, columnspan=9)
root.mainloop()
This question already has answers here:
tkinter creating buttons in for loop passing command arguments
(3 answers)
Closed 2 years ago.
I'm trying to create simple GUI like this:
three set of label, entry, and READ button, one set for one row
when READ button is pressed, the value of entry will be displayed on label.
But all Read button only read from the last entry and displayed on last label.
Here is my script:
import tkinter as tk
main = tk.Tk()
label = [None]*3
entry = [None]*3
for j in range(3):
label[j] = tk.StringVar()
tk.Label(main, textvariable = label[j], relief = 'raised', width = 7).place(x = 5, y = 40+30*j)
entry[j] = tk.Entry(main, width=8)
entry[j].place(x=80, y=40 + 30 * j)
tk.Button(main, text="READ", pady=0, padx=10, command= lambda: label[j].set(entry[j].get())).place(x=150, y=40 + 30 * j)
main.mainloop()
The problem with the code you sent is that the value of j is changing with the loop, so as the loop ends, all of your buttons and lables take the value of j as 3 (thats because when your loop ends, j has the value "3") so that means all of your lables and buttons are using the last label.
An easy fix would be to manually set label[j] and entry[j] to some other variable, then apply the command.
Something like this :
lambda x=label[j], y=entry[j]: x.set(y.get())
Here I first set label[j] to x and entry[j] to y and then change the values inside lambda.
import tkinter as tk
main = tk.Tk()
label = [None]*3
entry = [None]*3
read = [None]*3
for j in range(3):
label[j] = tk.StringVar()
tk.Label(main, textvariable = label[j], relief = 'raised', width = 7).place(x = 5, y = 40+30*j)
entry[j] = tk.Entry(main, width=8)
entry[j].place(x=80, y=40 + 30 * j)
read[j] = tk.Button(main, text="READ", pady=0, padx=10, command= lambda x=label[j], y=entry[j]: x.set(y.get()))
read[j].place(x=150, y=40 + 30 * j)
main.mainloop()
from tkinter import * // Libraries imported
import tkinter as tk
from tkinter import simpledialog
ROOT = tk.Tk()
strong textROOT.withdraw()
root = Tk()
s=[] //empty list to append entry values
i=0 // to iterate over for loop
for y in range(5):
r= Label(root, text="file_"+str(y)).grid(row=i) //5-labels created using for loop
i=i+1
i=0
for y in range(5):
r=("file_"+str(y)) //5 entry boxes created using for loop
r = Entry(root)
r.grid(row=i , column=1)
i=i+1
def getInput():
for y in range(5): //entry value is stored
r = ("file_"+str(y))
b = r.get()
s.append(b)
root.destroy()
Button(root, text = "submit",command = getInput).grid(row = 5, sticky = W)
//click box 'submit' is created to store values into empty list 's'//
mainloop() //code ends
//The code is showing error : AttributeError: 'str' object has no attribute 'get
//I am not able to store my entry values into an empty list S and later retrieve the entry values of that list.
r = ("file_"+str(y)) followed by b = r.get() won't magically retrieve the contents of the widget. You need to store your Entry widgets in a container like a list.
You could also get rid of the 2nd loop - why don't create both Label and Entry in the same loop?
import tkinter as tk
root = tk.Tk()
entries = []
for y in range(5):
tk.Label(root, text="file_"+str(y)).grid(row=y,column=0)
r = tk.Entry(root)
r.grid(row=y,column=1)
entries.append(r)
def getInput():
print ([ent.get() for ent in entries])
tk.Button(root, text = "submit", command = getInput).grid(row = 5, sticky = "w")
root.mainloop()
I have a small script that generates a random number of entry widgets. Each one needs a StringVar() so I can assign text to the widget. How can I create these as part of the loop since I won't know ahead of time as to how many there will be?
from Tkinter import *
import random
root = Tk()
a = StringVar()
height = random.randrange(0,5)
width = 1
for i in range(height): #Rows
value + i = StringVar()
for j in range(width): #Columns
b = Entry(root, text="", width=100, textvariable=value+i)
b.grid(row=i, column=j)
mainloop()
The direct answer to your question is to use a list or dictionary to store each instance of StringVar.
For example:
vars = []
for i in range(height):
var = StringVar()
vars.append(var)
b = Entry(..., textvariable=var)
However, you don't need to use StringVar with entry widgets. StringVar is good if you want two widgets to share the same variable, or if you're doing traces on the variable, but otherwise they add overhead with no real benefit.
entries = []
for i in range(height):
entry = Entry(root, width=100)
entries.append(entry)
You can insert or delete data with the methods insert and delete, and get the value with get:
for i in range(height):
value = entries[i].get()
print "value of entry %s is %s" % (i, value)
Just store them in a list.
vars = []
for i in range(height): #Rows
for j in range(width): #Columns
vars.append(StringVar())
b = Entry(root, text="", width=100, textvariable=vars[-1])
b.grid(row=i, column=j)
That said, you should probably be storing the Entry widgets themselves in a list, or a 2D list as shown:
entries = []
for i in range(height): #Rows
entries.append([])
for j in range(width): #Columns
entries[i].append(Entry(root, text="", width=100))
entries[i][j].grid(row=i, column=j)
You can then assign text to each widget with the insert() method:
entries[0][3].insert(0, 'hello')
I want to create a simple GUI where I can enter some values. A label before and at the and an button to start the script.
I was using something like this:
w = Label(master, text="weight:")
w.grid(sticky=E)
w = Label(root, text="bodyfathydrationmuscle:bones")
w.grid(sticky=E)
w = Label(root, text="hydration:")
w.grid(sticky=E)
its ok but i want to do it dynamic. also when i would use w for all the entrys i only could cast w.get once. but i need all my data ;-)
i was thinking of:
def create_widgets(self):
L=["weight","bodyfat","hydration","muscle","bones"]
LV=[]
for index in range(len(L)):
print(index)
print(L[index])
("Entry"+L[index])= Entry(root)
("Entry"+L[index]).grid(sticky=E)
("Label"+L[index])=Label(root, text=L[index])
("Label"+L[index]).grid(row=index, column=1)
To call later:
var_weight=Entryweight.get()
var_bodyfat=Entrybodyfat.get()
and so on. how can i make it work?
Your program suggests that Entrybodyfat and the other variables should be generated on the fly, but you don't want to do that.
The normal approach is to store the entries and labels in a list or a map:
from Tkinter import *
root = Tk()
names = ["weight", "bodyfat", "hydration", "muscle", "bones"]
entry = {}
label = {}
i = 0
for name in names:
e = Entry(root)
e.grid(sticky=E)
entry[name] = e
lb = Label(root, text=name)
lb.grid(row=i, column=1)
label[name] = lb
i += 1
def print_all_entries():
for name in names:
print entry[name].get()
b = Button(root, text="Print all", command=print_all_entries)
b.grid(sticky=S)
mainloop()
The value of the bodyfat entry is then entry["bodyfat"].get().