Creating StringVar Variables in a Loop for Tkinter Entry Widgets - python

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

Related

How do I update a specific row and column in tkinter table?

I am creating a table like this in tkinter, https://www.geeksforgeeks.org/create-table-using-tkinter/. I am unable to update specific sections, have not been able to find anything that works yet.
# code for creating table
for i in range(5):
for j in range(5):
example_table = tkinter.Entry(root, width=20, fg='blue',
font=('Arial',16,'bold'))
example_table.grid(row=i, column=j)
example_table.insert(tkinter.END, "f")
After creating the table, If I want to update the 4th row and 4th column, how would I do so?
The simplest way would be to keep a reference to each entry within the table class using a 2d list, and then you can just access each entry from it's index value
for example:
from tkinter import *
class Table:
def __init__(self,root):
self.entries = [] # now each of the entries will be stored in rows
# code for creating table
for i in range(total_rows):
row = [] # this will actually contain 1 row of cell entry widgets
for j in range(total_columns):
e = Entry(root, width=20, fg='blue',
font=('Arial',16,'bold'))
e.grid(row=i, column=j)
e.insert(END, lst[i][j])
row.append(e)
self.entries.append(row)
lst = [(1,'Raj','Mumbai',19),
(2,'Aaryan','Pune',18),
(3,'Vaishnavi','Mumbai',20),
(4,'Rachna','Mumbai',21),
(5,'Shubham','Delhi',21)]
# this is the function that updates the table
def updateTable(row, col):
e = t.entries[row][col] # get the entry at row, col
val = e.get() # Get the current text in cell
e.delete(0,last=len(val)) # remove current text
e.insert(END, "Something Differnet") # insert new text
root = Tk()
t = Table(root)
# clicking this button will change the cell text for 4th column 4th row
B = Button(root, text="Change Table", command=lambda: updateTable(3, 3))
B.grid(row=5,column=1, columnspan=2)
root.mainloop()

How do I access specific element of this Entry matrix

I am making a Sudoku game, so I want to create matrix of Entry elements which could be given a value of an existing board. I need to access specific element of that matrix and assign a value to it. I also need to know if I can lock Entry so it cannot be edited?
for i in range(9):
for j in range(9):
e = tk.Entry(root, bg='white', width=2, font=('calibri', 20), justify='center')
e.grid(row=i, column=j)
The simplest solution is to save the entries to a list or dictionary.
entries = {}
for i in range(9):
for j in range(9):
e = tk.Entry(root, bg='white', width=2, font=('calibri', 20), justify='center')
e.grid(row=i, column=j)
entries[i,j] = e
...
foo = entries[2,2].get()

Using lambda function in command of Button widget in tkinter [duplicate]

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

Accessing Entry widget created using for loop

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

tkinter create labels and entrys dynamically

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

Categories

Resources