Question

I have the following code (only sections of it) for getting the entries in 4 Entry boxes I have created. However I have two niggles:

  • When I type into each box, it types the same thing and I wish to type different numbers and assign all of them to separate variables.

  • Is there any way of producing 4 boxes in a loop and fewer lines than this?

    number = StringVar() def numberwritten(*args): number.trace("w", numberwritten) fg = number.get() print fg

    In separate definition def ChoiceBox(choice): (not full code under this def)

    def ChoiceBox(choice): i = [0, 1, 2, 3]

        for i in i:
            choice_title = Label(choice_frame, text='Value %g'% float(i+1), bg='white', borderwidth=0, width=0)
            choice_title.grid(row=0, column=column+i, sticky="nsew", padx=1, pady=1)
    
        box1 = Entry(choice_frame, bg='white', borderwidth=0, width=0, textvariable=number)
        box1.grid(row=1, column=0, sticky="ew", padx=1, pady=1)
        box2 = Entry(choice_frame, bg='white', borderwidth=0, width=0, textvariable=number)
        box2.grid(row=1, column=1, sticky="ew", padx=1, pady=1)
        box3 = Entry(choice_frame, bg='white', borderwidth=0, width=0, textvariable=number)
        box3.grid(row=1, column=2, sticky="ew", padx=1, pady=1)
        box4 = Entry(choice_frame, bg='white', borderwidth=0, width=0, textvariable=number)
        box4.grid(row=1, column=3, sticky="ew", padx=1, pady=1)
    

UPDATE/EDIT:

This is the section of code I have and cannot figure out what's going wrong with it at the end as I'm receiving syntax errors:

def numberwritten(number):
    fg = number.get()
    print fg

numbers = [StringVar() for i in xrange(4) ] #Name available in global scope. 
for i in numbers: 
    i.trace('w',lambda n=i: numberwritten(n) ) 


def ChoiceBox(choice):


    column = 0
    if choice == "Fixed":
        choice_frame.grid_forget()      
    tkMessageBox.showinfo("Message", "No optimisation, value fixed.")
    elif choice == "List":

        for i in xrange(4): 
            choice_title = Label(choice_frame, text='Value %g'% float(i+1), bg='white', borderwidth=0, width=0) 
        choice_title.grid(row=0, column=column+i, sticky="nsew", padx=1, pady=1) 
        boxes=[] 

        tkMessageBox.showinfo("Message", "Please fill in list values.")


    elif choice == "Interval" or "Optimisation":
        i = [0, 1]
        choice_title1 = Label(choice_frame, text='Min Value', bg='white', borderwidth=0, width=0)
        choice_title1.grid(row=0, column=column, sticky="N S E W", padx=1, pady=1)
        choice_title2 = Label(choice_frame, text='Max Value', bg='white', borderwidth=0, width=0)
        choice_title2.grid(row=0, column=column+1, sticky="nsew", padx=1, pady=1)

        boxes=[]

        tkMessageBox.showinfo("Message", "Enter Min/Max values.")

for i in xrange(4): 
        box=Entry(choice_frame,bg='white',borderwidth=0,textvariable=numbers[i]) 
        box.grid(row=1,column=i, sticky='ew', padx=1, pady=1 
        boxes.append(box)
    box1,box2,box3,box4=boxes
Was it helpful?

Solution

First, please stop using:

i=[1,2,3,4]
for i in i:
    ...

Use:

for i in (1,2,3,4):
    ...

instead.

Or better:

for i in xrange(1,5): #range in python3.x
    ...

Now, creating the stuff in the loop is easy:

strvars=[]
boxes=[]
for i in xrange(1,5):
    svar=StringVar()
    box=Entry(choice_frame, bg='white', borderwidth=0, width=0, textvariable=svar)
    box.grid(row=1, column=i-1, sticky="ew", padx=1, pady=1)
    svar.trace('w',numberwritten)
    #If you want to pass the box associated with the stringvar, you can do this:
    #svar.trace('w',lambda a,b,c,box=box : numberwritten(box)) #box.get() get's the contents of an Entry too!
    strvars.append(svar)
    boxes.append(box)

number1,number2,number3,number4=strvars  #unpack stringvars 
box1,box2,box3,box4=boxes   #unpack boxes

You need a distinct StringVar for each box. The unpacking only works if you know how many items there are in the lists holding the StringVars and Entry boxes. Otherwise, you can get references to the box/variable you want by boxes[0] and strvars[0] for example.

EDIT

Something like this should work...

def numberwritten(number):
    fg = number.get()
    print fg 

numbers = [StringVar() for i in xrange(4) ]  #Name available in global scope.
for i in numbers:
    i.trace('w',lambda a,b,c,n=i: numberwritten(n) )

# In separate definition def ChoiceBox(choice): (not full code under this def)
def ChoiceBox(choice):  

    for i in xrange(4):
        choice_title = Label(choice_frame, text='Value %g'% float(i+1), bg='white', borderwidth=0, width=0)
        choice_title.grid(row=0, column=column+i, sticky="nsew", padx=1, pady=1)

    boxes=[]
    for i in xrange(4):
        box=Entry(choice_frame,bg='white',borderwidth=0,textvariable=numbers[i])
        box.grid(row=1,column=i, sticky='ew', padx=1, pady=1
        boxes.append(box)

    box1,box2,box3,box4=boxes

As an aside, why are you using width=0 everywhere? an Entry/Label with no width is pretty much useless.

OTHER TIPS

The StringVar is a Model for the Entry (and a few other things in Tkinter). You've given each Entry instance a reference to the same StringVar object, so naturally they share the model and thus show the same contents. You'll need to make four different StringVar objects, one for each Entry. (Those, you'll create in a loop that is iterating over the collection of StringVars…)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top