I am making a program that lets a user input a flower type, and it will make a new row with row#, name, and days remaining before it dies. At the moment the UI is a bit messy and code could be improved a lot but that's not the point. I would like to know how I would go about making multiple new labels that I can change the days remaining with the click of a button.
Here is my code so far:
It runs ok but only the lastest made row can be changed, this is because every time one is made, the last one can't be edited anymore, and that's what I want to change.
from tkinter import *
#Flower Types
flowers_days = {
"peony": 1,
"rose": 2,
"daffodil": 3,
"dandelion": 4,
"lavender": 5
}
day_change = {}
#Variables
day = 1
days_left = 5
row_Num = 0
name = ""
#Commands
def new_flower():
#make a new line with the new flower
global row_Num
global days_left
global name
global new_row
row_Num += 1
name = str(clicked.get())
print("Test:" + name)
days_left = flowers_days[clicked.get()]
day_change[days_left] = int(row_Num)
new_row = Label(main_Frame, text=str(row_Num)+" "+name+" " + str(days_left))
new_row.pack()
return new_row
def next_day():
global days_left
global name
days_left -= 1
new_row.config(text=str(row_Num)+" "+name+" " + str(days_left))
root = Tk()
new_row = Label()
clicked = StringVar()
clicked.set("No option Selected")
#FLOWER TYPE
flower_Type_Frame = LabelFrame(root, text="New Flowers", padx=5, pady=5)
flower_Type_Frame.grid(row=0, rowspan=4, column=0, columnspan=2, padx=10, pady=10)
flower_Type_Label = Label(flower_Type_Frame, text="Flower Type:")
flower_Type_Label.grid(row=0, column=0, columnspan=2, padx=5, pady=5)
flower_Type_Drop = OptionMenu(flower_Type_Frame, clicked, """
No option Selected
""", "peony", "rose", "daffodil", "dandelion", "lavender")
flower_Type_Drop.grid(row=1, column=0, columnspan=2, pady=5, padx=5)
flower_Type_Submit = Button(flower_Type_Frame, text="Submit", padx=10, pady=10, command=new_flower)
flower_Type_Submit.grid(row=2, column=0, columnspan=2, rowspan=2)
#Empty slot
space_Frame = LabelFrame(root, text="Empty", padx=5, pady=5)
space_Frame.grid(row=0, rowspan=4, column=3, columnspan=2, padx=10, pady=10)
space_Fill = Label(space_Frame, text="Space ").grid(row=0, column=0)
#Day Pass
day_Pass_Frame = LabelFrame(root, text="Day Pass", padx=5, pady=5)
day_Pass_Frame.grid(row=0, rowspan=2, column=6, columnspan=4, padx=10, pady=10)
day_Pass = Button(day_Pass_Frame, text="Next Day", padx=10, pady=10, command=next_day)
day_Pass.grid(row=0, rowspan=2, column=3, columnspan=2)
#Row Delete
#Main stuff
main_Frame = LabelFrame(root, text="Flowers In Stock", padx=5, pady=5)
main_Frame.grid(row=5, column=0, columnspan=7, padx=10, pady=10)
header = Label(main_Frame, text=" Row # / Flower Type / Days Remaining ", padx=5, pady=5)
header.pack(padx=5, pady=5)
root.mainloop()
Once this is sorted I also plan on making it to have a remove row button, so the row numbers need to be able to be changed too if possible.
Thanks for any help.
You're keeping only one 'days_left' information (in a global variable), but you
need to keep one for each flower. So your main data structure needs to be a
list of flowers, and you should remove the 'global' statements for days_left,
name, new_row, as that information needs to be secific to each flower.
Add this to the global scope (just before the new_flower() definition):
# List of [name, days_left, label], one per flower
flowers = []
In the new_flower() function, add the newly-created flower to the list with 'append':
new_row = Label(main_Frame, text=str(row_Num)+" "+name+" " + str(days_left))
new_row.pack()
flowers.append([name, days_left, new_row])
The next_day function should look like this:
def next_day():
for i, f in enumerate(flowers):
# f is a 3-element list [name, days_left, label]
f[1] -= 1
name, days_left, label = f
label.config(text=str(i+1)+" "+name+" " + str(days_left))
The 'enumerate' call iterates over a list, returning both the current index in
the list (in 'i') and the current list item (in 'f'). The index gives you the
row number.
Related
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
Hello im having python learning project. I want to insert in GUI two numbers, which are defining range for program to generate random number from.
I am really having problems with calling function with press of the button. And constantly getting error ValueError: invalid literal for int() with base 10: '', when trying to convert string from entry in GUI to int and then inserting them into random.randint.
Thx for Help!
from tkinter import *
import random
root = Tk()
root.title("Generator custom random number")
#function that gets number from entry converts string to int and defines target number in stevilo
def function():
string_answer1 = prvo_stevilo.get()
int1 = int(string_answer1)
string_answer2 = drugo_stevilo.get()
int2 = int(string_answer2)
stevilo = random.randint(int1, int2)
#Defining GUI
navodilo = Label(root, text="Choose custom lower and upper number to chose random number from", width=60)
navodilo2 = Label(root, text="From", width=20, borderwidth=3)
navodilo3 = Label(root, text="To", width=20, borderwidth=3)
prvo_stevilo = Entry(root, width=20, borderwidth=3)
drugo_stevilo = Entry(root, width=20, borderwidth=3)
gumb = Button(root, text="Generate number", width=17, height=2, command=function)
praznavrstica = Label(root, text="")
izpis = Label(root, text="Random number is: ", width=20)
izpis_stevila = Label(root, text="" + stevilo)
#Showcase of gui
navodilo.grid(row=0, column=0, columnspan=1)
navodilo2.grid(row=1, column=0, columnspan=1)
navodilo3.grid(row=3, column=0, columnspan=1)
prvo_stevilo.grid(row=2, column=0, columnspan=1)
drugo_stevilo.grid(row=4, column=0, columnspan=1)
praznavrstica.grid(row=5, column=0, columnspan=1)
gumb.grid(row=6, column=0, columnspan=1)
praznavrstica.grid(row=7, column=0, columnspan=1)
izpis.grid(row=8, column=0, columnspan=1)
izpis_stevila.grid(row=9, column=0, columnspan=1)
#Loop
root.mainloop()
I've noticed few problems with your code. I was able to make it running without too many changes, although probably it is not the best way.
First answer to your question: you are getting this error, because you are trying to change string -> '' to int. It happens because function() is running before you click button.
Another problem:
izpis_stevila = Label(root, text="" + stevilo)
variable 'stevilo' simply doesn't exist before calling function(), so delete it from here.
My proposition for changes:
1)
gumb = Button(root, text="Generate number", width=17, height=2,command = lambda: function())
Without lambda your function will run no matter of state of your button.
2)
first = IntVar(root, value=0)
second = IntVar(root, value=1)
prvo_stevilo = Entry(root, width=20, borderwidth=3, textvariable=first)
drugo_stevilo = Entry(root, width=20, borderwidth=3, textvariable=second)
If you run function without any values in your entry you will get error. This change allows you to put default value for your entry widgets.
3)
def function():
if prvo_stevilo.get() == '' or drugo_stevilo.get() =='':
return
else:
string_answer1 = prvo_stevilo.get()
int1 = int(string_answer1)
string_answer2 = drugo_stevilo.get()
int2 = int(string_answer2)
stevilo = random.randint(int1, int2)
izpis_stevila = Label(root, text=str(stevilo))
izpis_stevila.grid(row=9, column=0)
Firstly check if your entry is not empty.
Secondly update label, also remeber about changing int to string here text=str(stevilo).
So I've been struggling with an issue for a week or so, been googling around trying to find different solutions, etc and getting nowhere. I was advised to put functioning code on here so I've cut it down some while still showing the issue.
I want to have a main page listing a set of goals, then if you click on the "Goal Entry" button up top a new window opens where you can input additional goals. Then you type in your desired additions, hit enter, and it adds it to the list on the main page.
I've accomplished all of the above EXCEPT, after you add the goals (and I have the list printing before and after so I know they're being added) and the entry window closes, the list of labels (created by an iteration) hasn't updated accordingly.
How do I get the list on the main page to automatically update when a new item is added to the list?
from tkinter import *
pg = ["goal1","goal2"]
pgtotal=1
psum=len(pg)
class yeargoals():
global pg, hg, fg, rg, rgtotal
def __init__(self,master):
self.master = master
master.title("This Year's Goals")
self.buttonframe = Frame(root)
self.buttonframe.pack(side=TOP, padx = 150, fill=BOTH)
self.home = Button(self.buttonframe, text="Home Page")
self.home.grid(row=1, column=1, padx=10)
self.enter = Button(self.buttonframe, text="Goal Entry", command=self.winenter)
self.enter.grid(row=1, column=2, padx=10)
self.finalize = Button(self.buttonframe, text="Finalize for Year")
self.finalize.grid(row=1, column=3, padx=10)
self.dashboard = Button(self.buttonframe, text="Goal Dashboard")
self.dashboard.grid(row=1,column=4, padx=10)
self.goalframe = Frame(root)
self.goalframe.pack(side=TOP, padx=150, pady=50, fill=BOTH, expand = True)
#Makes the label Fram I want the Checkboxes to go in
self.LabelFramep= LabelFrame(self.goalframe,text="Professional Goals")
self.LabelFramep.pack(side=LEFT, padx=10, anchor = N, fill=BOTH, expand = True)
#Makes the from the list above
for goal in pg:
l = Checkbutton(self.LabelFramep, text=goal, variable=Variable())
l.config(font=("Courier",12))
l.grid(sticky=W)
self.ptotal=Label(self.LabelFramep,text="Progress so far: "+str(pgtotal)+"/"+str(psum))
self.ptotal.config(font=("Courier",12))
self.ptotal.grid(sticky=W)
self.pper=Label(self.LabelFramep, text=str(round((pgtotal/psum)*100))+"% Complete")
self.pper.config(font=("Courier",12))
self.pper.grid(sticky=W)
def winenter(self):
global pg
self.winenter = Toplevel(root)
options = ["Professional", "Health", "Financial", "Reward Items"]
variable = StringVar(self.winenter)
variable.set(options[0])
#Title of entry section
t1 = Label(self.winenter, text="New Goal Entry")
t1.grid(row=0, column=1, columnspan=2)
#dropdown menu
d = OptionMenu(self.winenter, variable, *options)
d.grid(row=1, column=2)
#entry fields
e1 = Entry(self.winenter)
e1.grid(row=2, column=2, padx = 10, pady=5)
e2 = Entry(self.winenter)
e2.grid(row=3, column=2, padx=10, pady=5)
e3 = Entry(self.winenter)
e3.grid(row=4, column=2, padx=10, pady=5)
e4 = Entry(self.winenter)
e4.grid(row=5, column=2, padx=10, pady=5)
e5 = Entry(self.winenter)
e5.grid(row=6, column=2, padx=10, pady=5)
#Label for entry fields
l1 = Label(self.winenter, text="Goal Number 1")
l1.grid(row=2, column=1)
l2 = Label(self.winenter, text="Goal Number 2")
l2.grid(row=3, column=1)
l3 = Label(self.winenter, text="Goal Number 3")
l3.grid(row=4, column=1)
l4 = Label(self.winenter, text="Goal Number 4")
l4.grid(row=5, column=1)
l5 = Label(self.winenter, text="Goal Number 5")
l5.grid(row=6, column=1)
def enter():
global pg, main
print (pg)
if variable.get() == "Professional":
pg.append(e1.get())
self.winenter.destroy()
print (pg)
#Goal entry execute button
b = Button(self.winenter, text="Enter Goals", command=enter)
b.grid(row=7, column = 1)
root = Tk()
Window = yeargoals(root)
root.mainloop()
In your callback function to button "Enter Goals", you have done nothing to update your main window. Maybe you think the main window will magically keep updated with the variable pg, no, you need to do all those updates manually in your callback function.
For example, change your callback enter() to:
def enter():
global pg, main
print (pg)
if variable.get() == "Professional":
pg.append(e1.get())
l = Checkbutton(self.LabelFramep, text=pg[-1], variable=Variable())
l.config(font=("Courier",12))
l.grid(sticky=W)
self.winenter.destroy()
print (pg)
You can find the main window is updated after you click "Enter Goals".
I have programmed a script which takes random four elements from a table and question to the user using tkinter, random and sqlite3. Currently, I can ask a question. Implement four choices with radiobuttons. I can also test if the answer is correct or not and show the result to the user via toplevel().
Problem is, how can I refresh the question after the continue button clicked?
My whole code is below. I have tried refreshing the random numbers and labels under continue_asking or another def called from continue_asking. But it doesn't work at all.
from tkinter import *
from sqlite3 import *
from random import *
class Question(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.prepare_question()
def prepare_question(self):
self.tumu = {0:['ask1','answer1'], # instead of SQL query
1:['ask2','answer2'],
2:['ask3','answer3'],
3:['ask4','answer4']}
self.create_widgets()
def create_widgets(self):
self.choiceFrame = Frame(self)
self.choiceFrame.grid(row=2, column=0)
self.choiceNum = IntVar()
for i in range(4):
Radiobutton(self.choiceFrame, text=self.tumu[i][1], variable=self.choiceNum, value=i) \
.grid(row=2, column=i, padx=5, pady=5)
self.q_num = randrange(4)
self.q_word = self.tumu[self.q_num][0]
lbl_question = Label(self, text="Which one is the meaning of the word: " + self.q_word, font="Courier 12")
lbl_question.grid(row=0, column=0, columnspan=4, padx=5, pady=5, sticky=W)
txt_question = Text(self, height=1, font="Courier 12", pady=2)
txt_question.tag_configure("myStyle", font="Courier 12 bold")
txt_question.insert("end", "Please choose the answer and ")
txt_question.insert("end", "click okay to see the results.", "myStyle")
txt_question.configure(state="disabled")
txt_question.grid(row=1, column=0, columnspan=4, padx=5, sticky=W)
btn_okay = Button(self, text="Okay", font="12", command=self.a_control)
btn_okay.grid(row=3, column=0, columnspan=2)
def a_control(self):
self.choosenWord = self.q_num
self.frm_answer = Toplevel()
self.frm_answer.title("Result")
self.selectedWord = self.choiceNum.get()
txt_result = Text(self.frm_answer, height=4, width = 40)
if self.choosenWord == self.selectedWord:
txt_result.insert("end", "Congrats! Your answer is correct.\n")
else:
txt_result.insert("end","Your answer is not correct.\n")
txt_result.insert("end", "Correct answer is " + self.tumu[self.q_num][1] + '\n')
txt_result.insert("end", "Please click Continue to continue.\n")
txt_result.insert("end", "Click cancel to quit.")
txt_result.grid(row=0, column=0, columnspan=2, padx = 5, pady=5)
txt_result.configure(state="disabled")
btn_continue = Button(self.frm_answer, text="Continue", command=lambda: self.continue_asking(self.frm_answer))
btn_continue.grid(row=1, column=0, padx=5, pady=5, sticky = W)
btn_quit = Button(self.frm_answer, text="Cancel", command=self.end_asking)
btn_quit.grid(row=1, column=1, padx=5, pady=5, sticky = W)
def continue_asking(self,frm_answer):
frm_answer.destroy()
def end_asking(self):
root.destroy()
root = Tk()
app = Question(root)
root.mainloop()
I have tried adding prepare_question to continue_asking. It keeps asking questions but widgets are not changing. They are just overlapping.
EDIT
So let's restart from scratch, i was totally wrong because no widget was removed and they stacked in the main Frame children list.
You still don't need to write so much code, mostly move some parts.
First, to be able to update the widgets and prepare the new question peacefully, move
self.create_widgets() in the constructor and put the random index self.q_num and self.q_word inside prepare_question, since it belongs to the logic of the question creation.
In create_widgets() you only need to keep some control on the label question, so we add self.lbl_question...
Finally, i suggest to create a new function update_widgets(), but you can put the logic inside continue_asking().
In this function, call prepare_question to update the next question (sql query and random stuff). Since we move the random index, everything is ready to update each widget:
text of the question label
text of radiobuttons. I'm not so proud of the loop to change those, but that'll do the trick. (we keep the values created for the indexes to match the new ones, i'm not very sure about this logic with SQL queries, i follow your first implementation with text=self.tumu[i][1])
If someone can tell how to get the radiobutton value more easily, i'm interested
Here is the whole code:
from tkinter import *
from sqlite3 import *
from random import *
class Question(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.prepare_question()
self.create_widgets()
def prepare_question(self):
self.tumu = {0:['ask1','answer1'], # instead of SQL query
1:['ask2','answer2'],
2:['ask3','answer3'],
3:['ask4','answer4']}
self.q_num = randrange(4)
self.q_word = self.tumu[self.q_num][0]
def create_widgets(self):
self.choiceFrame = Frame(self)
self.choiceFrame.grid(row=2, column=0)
self.choiceNum = IntVar()
for i in range(4):
Radiobutton(self.choiceFrame, text=self.tumu[i][1], variable=self.choiceNum, value=i) \
.grid(row=2, column=i, padx=5, pady=5)
self.lbl_question = Label(self, text="Which one is the meaning of the word: " + self.q_word, font="Courier 12")
self.lbl_question.grid(row=0, column=0, columnspan=4, padx=5, pady=5, sticky=W)
txt_question = Text(self, height=1, font="Courier 12", pady=2)
txt_question.tag_configure("myStyle", font="Courier 12 bold")
txt_question.insert("end", "Please choose the answer and ")
txt_question.insert("end", "click okay to see the results.", "myStyle")
txt_question.configure(state="disabled")
txt_question.grid(row=1, column=0, columnspan=4, padx=5, sticky=W)
btn_okay = Button(self, text="Okay", font="12", command=self.a_control)
btn_okay.grid(row=3, column=0, columnspan=2)
def a_control(self):
self.choosenWord = self.q_num
self.frm_answer = Toplevel()
self.frm_answer.title("Result")
self.selectedWord = self.choiceNum.get()
txt_result = Text(self.frm_answer, height=4, width = 40)
if self.choosenWord == self.selectedWord:
txt_result.insert("end", "Congrats! Your answer is correct.\n")
else:
txt_result.insert("end","Your answer is not correct.\n")
txt_result.insert("end", "Correct answer is " + self.tumu[self.q_num][1] + '\n')
txt_result.insert("end", "Please click Continue to continue.\n")
txt_result.insert("end", "Click cancel to quit.")
txt_result.grid(row=0, column=0, columnspan=2, padx = 5, pady=5)
txt_result.configure(state="disabled")
btn_continue = Button(self.frm_answer, text="Continue", command=self.continue_asking)
btn_continue.grid(row=1, column=0, padx=5, pady=5, sticky = W)
btn_quit = Button(self.frm_answer, text="Cancel", command=self.end_asking)
btn_quit.grid(row=1, column=1, padx=5, pady=5, sticky = W)
def continue_asking(self):
self.frm_answer.destroy()
self.update_widgets()
def update_widgets(self):
self.prepare_question()
# change question text
self.lbl_question.configure(text = "Which one is the meaning of the word: " + self.q_word)
# change Radiobutton
for child in self.choiceFrame.children.values():
index = child.config()['value'][4]
child.configure(text = self.tumu[index][1])
if index == 0: # reset the focus
child.select()
def end_asking(self):
root.destroy()
root = Tk()
app = Question(root)
root.mainloop()
First crap post: (the not to do part)
You don't need to change so much code to fix the present issue, have you already tried the following ?
def continue_asking(self,frm_answer):
frm_answer.destroy()
self.prepare_question()
I won't review the whole code, there is another place for that, but you can also avoid the lambda when you call continue_asking(), since you store the frame in self.frm_answer
btn_continue = Button(self.frm_answer, text="Continue", command=self.continue_asking)
# [...]
def continue_asking(self):
self.frm_answer.destroy()
self.prepare_question()
I have created a table in Tkinter by repetition of widgets following the importation of a text file (which therefore creates new rows depending on the containing information).
The following image shows that I need to be able to create from column '7' onwards a separate area of entry boxes depending on the OptionMenu choice.
For an option list the user is asked how many entry boxes they wish to fill in (therefore 'n' boxes created). For a 'Fixed' value there should be no boxes and any before deleted. For two other options in the OptionMenu there is always a Min and Max value (2 boxes). Each value in these boxes needs to be collected following their input via the user.
I have previously had help with the possibility of create a new frame each time but if possible would like to use the same one. I have the following code for the choice:
if choice == "Fixed":
for i in xrange(self.number_boxes):
self.box[i].grid_remove()
self.choice_title.grid_remove()
self.frame_table.grid_columnconfigure(7, weight=0)
tkMessageBox.showinfo("Message", "Value fixed.")
elif choice == "List":
self.win2 = tk.Toplevel(self.root)
self.win2.title("List")
self.list_text = Label(self.win2, text="Please enter number of values to be used:")
self.list_text.grid(row=0, column=0, sticky="nsew", padx=1, pady=1)
self.value = StringVar()
self.list_values = Entry(self.win2, textvariable=self.value, justify="center")
self.list_values.grid(row=1, column=1, sticky="nsew", padx=1, pady=1)
list_button = ttk.Button(self.win2, text="Enter", command=self.ValueBox)
list_button.grid(row=2, column=1, sticky="nsew", padx=1, pady=1)
self.win2.mainloop()
column = 7
self.number_boxes = int(self.number_boxes)
self.numbers = [StringVar() for i in xrange(self.number_boxes) ]
self.box = []
for i in xrange(self.number_boxes):
self.clicked.append(False)
self.choice_title = Label(self.frame_table, bg=self.mycolour, borderwidth=0, width=10)
self.choice_title.grid(row=1, column=self.column, columnspan=self.number_boxes, sticky="nsew", padx=1, pady=1)
self.box.append(Entry(self.frame_table,bg='white',borderwidth=0, width=10, justify="center", textvariable=self.numbers[i], fg='grey'))
self.box[i].grid(row=self.row_list,column=self.column+i, sticky='nsew', padx=1, pady=1)
self.box[i].insert(0, "Value %g" % float(i+1))
self.box[i].bind("<Button-1>", lambda event : self.callback(event))
self.total_boxes = self.number_boxes * ( rows - 2 )
self.boxes=[]
self.boxes.append(self.box[i])
tkMessageBox.showinfo("Message", "Please fill in list values.")
for i in self.numbers:
i.trace('w',lambda : self.numberwritten() )
elif choice == "Min" or "Max":
self.numbers = [StringVar() for i in xrange(2) ] #Name available in global scope.
self.number_boxes = 2
self.box = []
for i in xrange(2):
self.clicked.append(False)
self.choice_title = Label(self.frame_table, bg=self.mycolour, borderwidth=0)
self.choice_title.grid(row=1, column=self.column, columnspan=2, sticky="nsew", padx=1, pady=1)
self.box.append(Entry(self.frame_table,bg='white',borderwidth=0,textvariable=self.numbers[i], justify='center', fg='grey'))
self.box[i].grid(row=self.row_list, column=self.column+i, sticky='nsew', padx=1, pady=1)
if i == 0:
self.box[0].insert(0, "Min value")
elif i == 1:
self.box[1].insert(0, "Max value")
self.box[i].bind("<Button-1>", lambda event : self.callback(event))
self.boxes=[]
self.boxes.append(self.box[i])
tkMessageBox.showinfo("Message", "Enter Min/Max values.")
for i in self.numbers:
i.trace('w',lambda a,b,n=i: self.numberwritten(n) )
UPDATE section
def numberwritten(self): # where the above code block is usually all indented differently in comparision to this.
self.numbers.get()
def callback(self, event, index):
if (self.clicked[index] == False):
self.box[index].delete(0, END)
self.box[index].config(fg='black')
self.clicked[index] = True
I don't want to bombard this question with code but if any other functions such as numberwritten are needed I can provide them. I would very much appreciate some help as I'm nearing the end of it but am struggling with the 'final touches'.
There are a few things fishy in the following loop (I'll add comments at the fishy spots).
for i in xrange(self.number_boxes):
self.clicked.append(False)
self.choice_title = Label(self.frame_table, bg=self.mycolour, borderwidth=0, width=10) #Fishy
self.choice_title.grid(row=1, column=self.column, columnspan=self.number_boxes, sticky="nsew", padx=1, pady=1)
self.box.append(Entry(self.frame_table,bg='white',borderwidth=0, width=10, justify="center", textvariable=self.numbers[i], fg='grey'))
self.box[i].grid(row=self.row_list,column=self.column+i, sticky='nsew', padx=1, pady=1)
self.box[i].insert(0, "Value %g" % float(i+1))
self.box[i].bind("<Button-1>", lambda event, index=i : self.callback(event, index))
self.total_boxes = self.number_boxes * ( rows - 2 ) #fishy
self.boxes=[] #fishy
self.boxes.append(self.box[i])
tkMessageBox.showinfo("Message", "Please fill in list values.") #fishy
First, you're creating the choice_title labels, but you're only keeping a reference to one of them that you're creating. perhaps you should change that to a list and append to it like you do with the box list.
Second, self.total_boxes doesn't need to be calculated every time through the loop. It can be calculated at the end (I think).
Third, self.boxes=[] should be moved before the loop. What you're doing is equivalent to: self.boxes=[self.box[i]] at every step of the loop. When you're done, you only have one box in your boxes list (the last one).
Fourth, you prompt the user with a message box at every iteration of the loop. Is that really what you want? Or is it an indentation error?
There may be more stuff here that is a little weird, but these give you a place to start. Here's how I think it should look:
self.box=[]
self.boxes=[]
self.choice_title=[]
for i in xrange(self.number_boxes):
self.clicked.append(False)
choice_title = Label(self.frame_table, bg=self.mycolour, borderwidth=0, width=10) #Fishy
choice_title.grid(row=1, column=self.column, columnspan=self.number_boxes, sticky="nsew", padx=1, pady=1)
self.choice_title.append(choice_title)
box=Entry(self.frame_table,bg='white',borderwidth=0, width=10, justify="center", textvariable=self.numbers[i], fg='grey')
self.box.append(box)
box.grid(row=self.row_list,column=self.column+i, sticky='nsew', padx=1, pady=1)
box.insert(0, "Value %g" % float(i+1))
box.bind("<Button-1>", lambda event, index=i : self.callback(event, index))
self.boxes.append(box) #This is still a little weird since self.box and self.boxes are essentially the same information.
self.total_boxes = self.number_boxes * ( rows - 2 ) #fishy
tkMessageBox.showinfo("Message", "Please fill in list values.")