how to assign the variable for python tkinter entry? - python

I am trying to create a simple 'SOS' puzzle game from Tkinter. I am creating an entry widgets grid using the grid method. Now I want an assigned variables for each entry. I try to do it using for loops but I can't use that variable the proper way. Can you help me? My question idea explain given below digram,
Code
for i in range(5):
for j in range(5):
self.entry=Entry(root,textvariable=f'{i}{j}')
self.entry.grid(row=i,column=j)
self.position.update({f"{i}-{j}":f"{i}{j}"})
enter code here

Instead of creating variables on the go, you should store the widgets made into a list or a dictionary. The list seems more reasonable as you can index it more easily.
Below is a simple, but full example that shows how you can make a 2-D list as well as search this list for the entry object:
from tkinter import * # You might want to use import tkinter as tk
root = Tk()
def searcher():
row = int(search.get().split(',')[0]) # Parse the row out of the input given
col = int(search.get().split(',')[1]) # Similarly, parse the column
obj = lst[row][col] # Index the list with the given values
print(obj.get()) # Use the get() to access its value.
lst = []
for i in range(5):
tmp = [] # Sub list for the main list
for j in range(5):
ent = Entry(root)
ent.grid(row=i,column=j)
tmp.append(ent)
lst.append(tmp)
search = Entry(root)
search.grid(row=99,column=0,pady=10) # Place this at the end
Button(root,text='Search',command=searcher).grid(row=100,column=0)
root.mainloop()
You have to enter some row and column like 0,0 which refers to 1st row, 1st column and press the button. Make sure there are no spaces in the entry. You should not worry much about the searching part, as you might require some other logic. But instead of making variables on the go, you should use this approach and store it in a container.
Also a note, you do not have to use textvariable as here the need of those are totally none. You can do whatever you want with the original object of Entry itself. Just make sure you have the list indexing start from 0 rather than 1(or subtract 1 from the given normal values).

Related

Python: Tkinter :Dynamically Create Label

I am trying to create Label Dynamically , I am getting invalid Syntax. Can you please help me what i am missing or any alternative
crsr = cnxn.execute(query)
row_num=2
column_num=0
Variable_Number=1
for row in crsr.fetchall():
test='Column_Label'+str(Variable_Number)+' = tk.Label(frame,text="'+row[0]+'")'
#proper Indentation availabe in code test1='Column_Label'+str(Variable_Number)+'.grid(row='+str(row_num)+',column='+str(column_num)+')'
eval(test+';'+test1)
# eval(test1)
row_num+=1
column_num+=1
root.update_idletasks()
You should not be using exec. If you want to associate a computed name with a widget in a loop, use a dictionary:
labels = {}
varnum = 0
for row in crsr.fetchall():
name=f"label#{varnum}"
labels[name] = tk.Label(frame, text=str(row[0]))
labels[name].grid(row=row_num, column=column_num
varnum += 1
row_num+=1
column_num+=1
If you don't really care what the name is, you can store the widgets in a list rather than a dictionary, and then reference them using an integer index (eg: labels[0], labels[1], etc).
Use exec() instead eval()
eval will evaluate a expression, not run it like you want.
Think of eval like the argument of a if statement.

How do you dynamically assign a list of buttons the same function but different arguments?

I have a python program using Tkinter that dynamically creates buttons that are identical except for their position/index. The buttons are created through a loop and are stored in a list. Therefore the buttons are only identifiable via their index in the list.
I am trying to loop through this list later and assign the buttons a function who's only argument is that button's indexed position in the list. For example:
for i in range(len(button_list)):
button_list[i].config(command=lambda: start_time(button_list[i]))
Because the argument is assigned when the button is clicked rather than when the function is assigned to the button, clicking any button always activates what should be the final button's function instead of its own function.
Is there a way to assign an argument to the function when the function is assigned to the button?
Here is the window with the buttons:
Window with Buttons
Here is a hard-coded example of what I'm trying to do:
button_list[0].config(command=lambda: start_time(0))
button_list[1].config(command=lambda: start_time(1))
button_list[2].config(command=lambda: start_time(2))
I've also tried this:
index_list = list(range(len(button_list)))
for x in index_list:
onclick = lambda index=x: start_time(x)
button_list[x].config(command=onclick)
Any help would be appreciated. Thanks
EDIT: Here is some more of my code to give more context for the sake of clarity:
def start_time(index):
now_local = datetime.now()
hour = now_local.strftime("%H")
minute = now_local.strftime("%M")
second = now_local.strftime("%S")
global time_start
time_start = [hour, minute, second]
global button_list
button_list[index].config(text="Stop", command=lambda: end_time(index))
for i in range(len(button_list)):
if i == index:
continue
else:
button_list[i].config(state=DISABLED)
I am not 100% sure what you are asking, but if I understand you right you want to assign the index of the button list to the start(time) within the config file for that indexed button.
If I am understanding right you can use enumerate() to solve the problem:
for ind, button in enumerate(button_list):
button_list[ind].config(command= lambda: start_time(ind)

How to add variable name on a python tk.entry made in a for loop

I'm making a form with repetitive user input so i made the entry boxes using a for loop. However assigning them a unique variable name isn't possible. For example:
for n in range(10):
tk.Entry().grid(row = 0, column = n)
Is there any way to have it be assigned to a variable automatically or I should make all 10 entry box with a variable name manually?
Maybe you can use a list like this:
entries = []
for n in range(10):
entries.append(tk.Entry())
entries[n].grid(row = 0, column = n)
and later access the entries by index...

Return multiple selections from tk listbox

I have a listbox and would like to be able to return multiple selections from said listbox.
I have tried changing "seltext" variable to a list(map(int()))) format, but I get the error of bad listbox index.
I'm not sure how to go about this; any help is appreciated.
The way I'm currently identifying the selected variable:
def selecting(self,event):
sel = self.lbox.curselection()
seltext = self.lbox.get(sel)
self.labelVariable.set(seltext)
The way that I'm assigning a single selection.
def OnButtonClick(self):
global confirmedsel
confirmedsel = ""
sel = self.lbox.curselection()
seltext = self.lbox.get(sel)
confirmedsel = seltext
print(confirmedsel)
app.quit()
The curselection method of the listbox returns a tuple of indexes representing the items that were selected. You simply need to iterate over that list and call the get method to get each element.
You do this in one line using a list comprehension, which results in a list that contains the values of the selected items as strings:
seltext = [self.lbox.get(index) for index in self.lbox.curselection()]
If you find list comprehensions difficult to read, here is a solution using a simple loop:
results = []
for index in self.lbox.curselection():
results.append(self.lbox.get(index))
def selecting(self,event):
sel = self.lbox.curselection()
seltext = list(map(int,self.lbox.get(sel)))
self.labelVariable.set(seltext)
Have you tried this?
You can lookup use of curselection here:
http://effbot.org/tkinterbook/listbox.htm

Append series of items to list with similar names in Python

I have a series of lists with two items in each of them called box1, box2, box3, etc. and am trying to append to a master list to access later. Below is what I thought would work, but it is not. I think it may be something with the string in the append method adding to i, but I am not sure.
This is obviously only adding the string box + i, but I need to figure out a way to loop through and add all similarly named items to this list. What is the best way to accomplish this goal?
box1 = [1,2]
box2 = [3,4]
boxes = []
##Adding strings. I need to add box items instead.
for i in range(11):
boxes.append("box" + str(i))
I want to see this:
boxes = [[1,2],[3,4]]
FYI: I cannot use imported libraries for this due to the software I am limited to using.
for i in range(11):
box = locals().get('box' + str(i))
if box is not None:
boxes.append(box)
Note that it would be better in my opinion to refactor your code so that instead of defining the variables box1, box2, etc. you would create a dictionary and then do something like box_dict['box1'] = [1, 2]. This would allow you to easily lookup these lists later by the name.
You can use eval(), in your case it will be:
boxes = [eval('box%d' %i) for i in range(1,3)]
If you have a list with the box names you want to add to boxes, you can simply do:
boxes = [eval(boxname) for boxname in boxnames]
This should work:
box1 = [1,2]
box2 = [3,4]
boxes = []
##adding strings, need to add box items instead
for i in range(1,3):
boxes.append(locals()["box" + str(i)])
boxDict={}
boxes=[]
for i in range(1,11):
box = [i, i+1]
boxDict[i] = box
boxes.append(box)
This is rather a poor way to code, but you can do it like this
import itertools
boxes=[]
for i in itertools.count(1):
name='box{}'.format(i)
if name not in locals():
break
boxes.append(locals()[name])
For the no-libraries version:
boxes=[]
i=1
while True:
name='box{}'.format(i)
if name not in locals():
break
boxes.append(locals()[name])
i+=1
One can use the vars() function to get a dictionary of available variables:
box1 = [1,2]
box2 = [3,4]
boxes = []
##Adding strings. I need to add box items instead
for i in range(11):
key = "box%d" % i
if key in vars():
boxes.append(vars()[key])
boxes
Also, you should consider to check globals().
Your question is similar to Stack Overflow question Convert a string to preexisting variable names, but to save time, you can use getattr(object, name) to get a variable with a particular name out of an object.
You might have something like:
for i in range(11):
boxes.append(getattr(self, "box"+i))

Categories