How do I access specific element of this Entry matrix - python

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

Related

Why are the text of my buttons getting the same text of the last item of a CSV file?

So I have this CSV file:
Number of studs,Name
1,A
2,B
3,C
4,D
5,E
6,F
7,G
8,H
9,I
10,J
11,K
12,L
13,M
14,N
15,O
16,P
17,Q
And my code creates one button for each item in the number of studs column and the text gets the item in Name column respectively
here's the code that do this:
def widget_creator():
for i in df['Number of studs']:
for n in df['Name']:
row, col = divmod(i, 3)
ct.CTkButton(new_frame, text= n, text_font = ('Montserrat', 15, 'bold'), corner_radius=10, fg_color=random.choice(colors), text_color='#FFFFFF').grid(row=row, column=col, pady=100, padx=50, ipadx = 100, ipady=130)
But now the problem is the buttons don't get the item in the Name column of their respective row but all the buttons get the last item in their text. Like the last item is Q in the Name column so every button has Q in their text instead of having the name in their respective row.
How can I fix this?
Thanks
I have not tested (no python available) but this should work:
def widget_creator():
for i, n in enumerate(df['Name'], start=1):
row, col = divmod(i, 3)
ct.CTkButton(new_frame, text= n, text_font = ('Montserrat', 15, 'bold'), corner_radius=10, fg_color=random.choice(colors), text_color='#FFFFFF').grid(row=row, column=col, pady=100, padx=50, ipadx = 100, ipady=130)
EDIT : Maybe even better but still not tested
def widget_creator():
for i, n in zip(df['Number of studs'],df['Name']):
row, col = divmod(i, 3)
ct.CTkButton(new_frame, text= n, text_font = ('Montserrat', 15, 'bold'), corner_radius=10, fg_color=random.choice(colors), text_color='#FFFFFF').grid(row=row, column=col, pady=100, padx=50, ipadx = 100, ipady=130)

How to pass two lists from different functions into save() function in Tkinter

I have two functions that create X number of entry widgets based on the number a user inputted:
def Pap_geo():
num_Pap = int(Pap.get())
Pap_GEOs = []
for i in range(num_Pap):
gt_geo = Entry(top, width=20)
gt_geo.focus_set()
gt_geo.grid(row=2+i, column=0, padx=20, pady=0, sticky="W")
Pap_GEOs.append(gt_geo)
return Pap_GEOs
and:
def Sap_geo():
num_Sap = int(Sap.get())
Sap_GEOs = []
for i in range(num_Sap):
Sap_geo = Entry(top, width=20)
Sap_geo.focus_set()
Sap_geo.grid(row=2 + i, column=1, padx=20, pady=0, sticky="W")
Sap_GEOs.append(Sap_geo)
return Sap_GEOs
I want to be able to click 'ok' and print the results of these two lists. I've gotten as far as:
def save():
Pap_GEOs2 = []
for j in Pap_geo():
Pap_GEOs2.append(j.get())
print(Pap_GEOs2)
Sap_GEOs2 = []
for j in Sap_geo():
Sap_GEOs2.append(j.get())
print(Sap_GEOs2)
button = Button(top, text="Save", command=save)
button.grid(row=1, column=1, padx=(170, 0), pady=(0, 10), sticky="W")
This prints two lists of the correct length, however they are empty. I had a similar question before, which was resolved. The solution was to create a list of the entry widgets then call get() on each of those widgets in the OK function. I thought that's what I was doing here but I am getting the same issue. Any input would be appreciated.
Thank you

Get input values from a grid with several Entry widgets on Tkinter

I'm trying to create a sudoku solver. I have my grid with the entries at this point but I don't know how to get the values that the user has put in them.
I have no clue yet as to how I'm going to make the Sudoku solver but I think I'll first have to find a way to store the input in some variable(s) so I can work with them later on.
So my question is, how do I get the values that have been filled into the entries?
This is my code thus far:
from tkinter import *
root = Tk()
root.title('Sudoku Solver')
root.geometry('500x400')
mylabel = Label(root, text='Fill in the numbers and click solve').grid(row=0, column=0, columnspan=10)
# Create the grid
def beg():
global e
cells = {}
for row in range(1, 10):
for column in range(1, 10):
if ((row in (1,2,3,7,8,9) and column in (4,5,6)) or (row in (4,5,6) and column in (1,2,3,7,8,9))):
kleur='black'
else:
kleur='white'
cell = Frame(root, bg='white', highlightbackground=kleur,
highlightcolor=kleur, highlightthickness=2,
width=50, height=50, padx=3, pady=3, background='black')
cell.grid(row=row, column=column)
cells[(row, column)] = cell
e = Entry(cells[row, column], width=4, bg='white', highlightthickness=0, fg='black', relief=SUNKEN)
e.pack()
# Tell the button what to do
def solve():
global e
test = e.get()
print(test)
# Create the buttons and give them a command
clearer = Button(root, text='Clear', command=beg)
solver = Button(root, text='Solve', command=solve)
# Locate the buttons
clearer.grid(row=11, column=3, pady=30)
solver.grid(row=11, column=7, pady=30)
# Run it for the first time
beg()
root.mainloop()
I also tried changing e to e[row, column] but that gave me a syntax error.
Standard rule: if you have many elements then keep them on list or dictionary.
Do the same as with cells
Create dictionary
entries = {}
add to dictionary
entries[(row, column)] = e
and get from dictionary
def solve():
for row in range(1, 10):
for column in range(1, 10):
print(row, column, entries[(row, column)].get() )
# from tkinter import * # PEP8: `import *` is not preferred
import tkinter as tk
# --- functions ---
# Create the grid
def beg():
# remove old widgets before creating new ones
for key, val in cells.items():
print(key, val)
val.destroy()
for row in range(1, 10):
for column in range(1, 10):
if ((row in (1,2,3,7,8,9) and column in (4,5,6)) or (row in (4,5,6) and column in (1,2,3,7,8,9))):
kleur='black'
else:
kleur='white'
cell = tk.Frame(root, bg='white', highlightbackground=kleur,
highlightcolor=kleur, highlightthickness=2,
width=50, height=50, padx=3, pady=3, background='black')
cell.grid(row=row, column=column)
cells[(row, column)] = cell
e = tk.Entry(cell, width=4, bg='white', highlightthickness=0, fg='black', relief='sunken')
e.pack()
entries[(row, column)] = e
# Tell the button what to do
def solve():
for row in range(1, 10):
for column in range(1, 10):
print(row, column, entries[(row, column)].get() )
# --- main ---
entries = {}
cells = {}
root = tk.Tk()
root.title('Sudoku Solver')
root.geometry('500x400')
mylabel = tk.Label(root, text='Fill in the numbers and click solve')
mylabel.grid(row=0, column=0, columnspan=10)
# Create the buttons and give them a command
clearer = tk.Button(root, text='Clear', command=beg)
solver = tk.Button(root, text='Solve', command=solve)
# Locate the buttons
clearer.grid(row=11, column=2, pady=30, columnspan=3) # I added `columnspan=3`
solver.grid(row=11, column=6, pady=30, columnspan=3) # I added `columnspan=3`
# Run it for the first time
beg()
root.mainloop()

Creating StringVar Variables in a Loop for Tkinter Entry Widgets

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

Create list of entries

I have a GUI with a x-number of entries. I want the output to be like a list of all the entries. I have the following code:
from Tkinter import *
master = Tk()
lijst=[]
x=0
while x<3:
a="e"+str(x)
lijst.append(a)
x=x+1
x=0
labels=[]
x=1
while x<4:
a="File"+str(x)+":"
labels.append(a)
x=x+1
x=0
while x<3:
a=labels[x]
b=Label(master,text=a)
b.grid(row=x+1, column=0)
x=x+1
x=0
while x<3:
a=lijst[x]
b=Entry(master)
b.grid(row=x+1, column=1)
c=Label(master, text=".txt ")
c.grid(row=x+1, column=1,sticky=E)
x=x+1
Button(master, text='Enter', command=???,width=20).grid(row=4, column=2, sticky=W, pady=4,padx=20)
mainloop()
output: list=[e0.get(),e1.get(),etc...
How can i create a list that looks like output and does not depend on the number of entries?
You can create the list of entries more easily using a comprehension list:
entries = [Entry(master) for i in range(3)]
for i, entry in enumerate(entries):
label_text = "File%s:" % (i+1)
Label(master, text=label_text).grid(row=i, column=0)
entry.grid(row=i, column=1)
Label(master, text=".txt").grid(row=i, column=2, padx=(0, 15))
Once thit list is created, print the get() call of each entry is trivial:
def print_entries():
print [entry.get() for entry in entries]
Button(master, text='Enter', width=20, command=print_entries).grid(row=4, column=3, sticky=W, pady=4,padx=20)
I have replaced the trailing withespaces of the ".txt" string with right padding as explained here, which is more clear.

Categories

Resources