Reputation: 229
I am new to python and tkinter, so I am having trouble with naming entry widgets that are created inside a for loop. The goal is for my GUI to solve the user's linear programming optimization problem for fun. I first ask the user how many variables there are in their problem, lets say n variables is inputted. Then I create a for loop that creates n entry widgets corresponding to each variable to store the coefficient value of that variable. I know how to create a single entry widget and name it so I can access it via name.get(). In my code, I tried to create a string name = "x" + str(i) where i is the for loop incrementing variable. But then when I for example call x1.get() I get an error that x1 is not defined. How do I fix this? And thanks for the help in advance.
import tkinter as tkr
def objCos():
x1Co = x1.get()
print(x1Co)
def objFunction():
global varFrame
numOfVars = ofEntry.get()
numOfVars = int(numOfVars)
varFrame.destroy()
varFrame = tkr.Frame(root)
varFrame.pack(side = tkr.BOTTOM)
varLabel = tkr.Label(varFrame, text = "Enter Objective Function Coefficients: ")
varLabel.grid(row = 0, columnspan = 2)
for i in range(1,numOfVars+1):
strName = 'x' + str(i)
strName = tkr.Entry(varFrame)
strName.grid(row = i, column = 1)
lbName = "varLabel" + str(i)
lbName = tkr.Label(varFrame, text = "x"+ str(i) + " = ")
lbName.grid(row = i, column = 0)
varButton = tkr.Button(varFrame, text = "Update Objective Function Coefficients",
bg = "light grey", command = objCos)
varButton.grid(row = numOfVars + 1, columnspan = 2)
root = tkr.Tk()
ofFrame = tkr.Frame(root)
ofFrame.pack(side = tkr.TOP)
global varFrame
varFrame = tkr.Frame(root)
varFrame.pack(side = tkr.BOTTOM)
ofLabel = tkr.Label(ofFrame, text = "Enter Number of Variables: ")
ofLabel.grid(row = 0, column = 0)
ofEntry = tkr.Entry(ofFrame)
ofEntry.grid(row =0, column = 1)
ofButton = tkr.Button(ofFrame, text = "Update Number of Variables",
bg = "light grey", command = objFunction)
ofButton.grid(row = 1, columnspan = 2)
root.mainloop()
Upvotes: 0
Views: 2503
Reputation: 3824
You can have a list of Entry widgets. Below I've amended part of your code to append each Entry to entries
as it's created.
entries = []
for i in range(1,numOfVars+1):
entries.append(tkr.Entry(varFrame))
entries[-1].grid(row = i, column = 1) # Grid the last item in entries
lbName = "varLabel" + str(i)
lbName = tkr.Label(varFrame, text = "x"+ str(i) + " = ")
lbName.grid(row = i, column = 0)
You can use the list to access the data entered later.
As an aside tkinter is generally imported as tk not as tkr. It doesn't affect the operation but helps others understand what you've done.
Upvotes: 2
Reputation: 189
For example, you can use simple structure to hold that vidgets, here is a example in one of mine old functions :)
Like there, self.creation_panel
is a dict.
def creation_view(self, core_line, skills_line):
#### Navigate functions for main menu ####
def set_navigate(self, arg):
self.navigate = arg
#### Configurations for create interference ####
self.configure_grid_x(20)
self.configure_grid_y(5)
row = 0
col = 0
#### Create body of view ####
for txt in core_line:
if col == 12:
col = 0
row += 1
self.creation_panel[txt] = Button(self.frame, text=txt, command=lambda cls=self, arg=txt: set_navigate(cls, arg))
self.creation_panel[txt].grid(row=row, column=col, columnspan=3, sticky=NSEW)
col += 3
for txt in skills_line:
if col == 12:
col = 0
row += 1
self.creation_panel[txt] = Button(self.frame, text=txt, state=DISABLED, command=lambda cls=self, arg=txt: set_navigate(cls, arg))
self.creation_panel[txt].grid(row=row, column=col, columnspan=4, sticky=NSEW)
col += 4
self.creation_panel["Preview"] = Button(self.frame, text="Preview", command=lambda cls=self: set_navigate(cls, "Preview"))
self.creation_panel["Preview"].grid(row=row+1, column=0, columnspan=12, sticky=NSEW)
self.preview_window1 = Label(self.frame, text="", justify=LEFT)
self.preview_window1.grid(row=0, rowspan=5, column=12, columnspan=4, sticky=NSEW)
self.preview_window1.config(state='disabled', relief=SUNKEN)
self.preview_window2 = Label(self.frame, text="", justify=LEFT)
self.preview_window2.grid(row=0, rowspan=5, column=16, columnspan=4, sticky=NSEW)
self.preview_window2.config(state='disabled', relief=SUNKEN)
self.frame.pack(side=LEFT, fill=BOTH, expand=1)
Maybe it isn't a the best way, and some other will correct me. But there is a one of possible ways.
self.navigate
variable was used for navigation becouse that class represents only view in MVC model of GUI :). If it has changed, then from controller is sended signal, get new model and called new view. Or somesimilar way, i don't clearly remember that old project.
Upvotes: 1