Let's start with a bit of background on what I'm trying to accomplish: I have a row of entry widgets corresponding to names (one entry per name, one name is equivalent to one column). When a number is entered in a particular entry, that entry is disabled and a "+" button appears beneath it. When that button is pressed, I want there to be an entry widget that replaces the "+" button (basically replace it).
To check if an entry has a value inside, I use a for loop. If there is a value, it is disabled, and a button is created, with the button's column position passed as a parameter to its command function in order to be able to appropriately place the new entry on the grid. However, when the button is pressed, it places the new entry at the last column position (basically, the last column checked in the loop). At first, I had tried to do this by creating the "+" button on-the-fly, however I quickly realized that if multiple entries had values, it couldn't properly transmit the position values.
To address this, I stored a "+" button for eevry column in a dict and then place those buttons on the grid when there is a value in the corresponding entry. This still doesn't work, however, as the new entry only appears at the last column no matter which button is pressed. The issue seems to be the column value that is passed to the addValue function.
Here's the problematic area of code (keep in mind, I started coding about 6 months ago):
def callback(*args):
self.SaveFile()
#remove preexisting entries from frame
for label in self.grid_slaves():
if int(label.grid_info()["column"]) > 0 and int(label.grid_info()["row"]) > 1:
label.grid_forget()
#set tkinter StringVar to task variable
task = optionvar.get()
#create a dictionary of entry values
if self.entries[task]!={}:
#check if values are already present in dataframe for this row/index
#if values are present, show them in entries
for i in range(len(NAMES)):
if self.entries[task][NAMES[i]].get() != "":
c = workers[NAMES[i]].col
#if a value is already present, disable entry box. User will have to go to the menu to add or edit
self.entries[task][NAMES[i]].configure(state = "disabled")
workers[NAMES[i]].isvalue[task] = True
#addbutt = tk.Button(self, text = "+",command=lambda:self.addValue(3,addbutt.grid_info()["column"],task))
#addbutt.grid(row=3,column=i+1)
#workers[NAMES[c-1]].widgets["addbutton"] = tk.Button(self, text = "+",command=lambda:self.addValue(3,c,task))
#workers[NAMES[c-1]].widgets["addbutton"].grid(row=3,column=c)
self.entries[task][NAMES[i]].grid(row=2, column=i+1, padx=2, pady=5)
for i in workers:
if workers[i].isvalue[task] == True:
workers[i].widgets["addbutton"] = tk.Button(self, text = "+",command=lambda:self.addValue(3,workers[i].col,task)) #THIS LINE SEEMS TO BE WHERE THE PROBLEM STEMS FROM - the value that is passed in the addValue function. (the problem seems to be caused by the loop?)
workers[i].widgets["addbutton"].grid(row=3,column=workers[i].col)
else:
#if no values present, show blank entries
for i in range(len(NAMES)):
self.entries[task][NAMES[i]] = tk.Entry(self,width=12)
self.entries[task][NAMES[i]].grid(row=2, column=i+1, padx=2, pady=5)
optionvar.trace("w",callback)
for i in range(len(NAMES)):
workers[NAMES[i]].widgets["mainentry"] = tk.Entry(self,state="disabled", width=12)
workers[NAMES[i]].widgets["mainentry"].grid(row=2,column=i+1)
workers[NAMES[i]].widgets["addentry"] = tk.Entry(self,width=12)
#self.entries[NAMES[i]] = tk.Entry(self,width=12)
def addValue(self,r,c,task):
#adds inout value to dataframe at specified row and column.
def addvar(name, task, b):
n = self.SaveFile(add=True, name=name, task=task, b=b)
self.df[name][task] = int(self.df[name][task])+int(b)
self.entries[task][name].configure(state = "normal")
self.entries[task][name].delete(0, "end")
self.entries[task][name].insert(0,str(self.df[name][task]))
self.entries[task][name].configure(state = "disabled")
workers[name].widgets["addentry"].delete(0,"end")
self.SaveFile()
print(self.df)
for label in self.grid_slaves():
if int(label.grid_info()["column"]) == c and int(label.grid_info()["row"]) == r:
label.grid_forget()
#entry = tk.Entry(self, width=12)
workers[NAMES[c-1]].widgets["enterbutton"] = tk.Button(self,text="Enter", command = lambda: addvar(name=NAMES[c-1], task=task, b=workers[NAMES[c-1]].widgets["addentry"].get()))
workers[NAMES[c-1]].widgets["addentry"].grid(row=r,column=c) #THIS IS THE LINE THAT PLACES THE NEW ENTRY AT AN ERRONEOUS POSITION
workers[NAMES[c-1]].widgets["enterbutton"].grid(row=r+1,column=c)