0

I'm a python/Tkinter newbie, so in advance I'll ask you not to throw bananas/rotten tomatoes/feces in my direction.

I'm writing some code that will be used as a data logger which will be build to capture several data values. Currently the program reads a set of survey lines and data points from a mysql database and populates the existing values into Entry elements with a button next to each element. The concept is that when a user clicks a button next to the adjacent Entry element, the Entry value will be updated with the new data value.

The specific problem I am having resides in passing the Entry element name to a function to overwrite its contents:

for row in rows:
    cnt=cnt+1
    Label(frame, text="Station: "+str(row[2]), bg=backcolor).grid(row=cnt, column=0)
    e1 = Entry(frame)
    e1.config(width=5)
    if row[5]!="":#ensure data value is not null, or insert empty space
        e1.insert(0, str(row[5]))
    else:
        e1.insert(0, " ")
    e1.grid(row=cnt,column=1)
    e2 = Button(frame, text="Log Data "+str(row[0]), command=lambda: saveData(e1))
    e2.grid(row=cnt, column=2)
...
def saveData(entryid):
    print Entry.get(entryid)

The problem lies with the saveData(e1). It appears to only pass the last element generated by the For row in rows constructor. What am I missing here to tie each button to its specific Entry element?

BTW, I am using Python 2.7

Thanks in advance for your assistance.

Here's the solution that Curly Joe pointed me to:

def saveData(stationdata):
    print Entry.get(stationdata)
def getData():
    #DATA TO GET SQL RESULTS/PREPARE FRAMED CANVAS ELEMENT HERE FOR SCROLLBARS
    for row in rows:
        cnt=cnt+1
        Label(frame, text="Station: "+str(row[2]), bg=backcolor).grid(row=cnt, column=0)
        e1 = Entry(frame)#Data Entry 
        e1.config(width=5)
        if row[5]!="":
                e1.insert(0, str(row[5]))
        else:
                e1.insert(0, "NA")
        e1.grid(row=cnt,column=1)
        e2 = Button(frame, text="Log Data "+str(row[0]), command=partial(saveData, e1))
        e2.grid(row=cnt, column=1)
Max
  • 95
  • 1
  • 13

1 Answers1

-1

Callbacks always get the event as the first parameter. Try changing

def saveData(entryid)

to

def saveData(event, entryid)
saulspatz
  • 5,011
  • 5
  • 36
  • 47
  • I think I see where you're going with that. What would be the input for the 'event' in the line e2 = Button(frame, text="Log Data "+str(row[0]), command=lambda: saveData(e1)) – Max Dec 23 '15 at 22:02
  • _"Callbacks always get the event"_ - not true, if the callback is associated with the `command` attribute. The event is only passed in when you use `bind`. – Bryan Oakley Dec 23 '15 at 22:53
  • So why does the command attribute not pass the name of the Entry element, e1? It passes only the last e1 name in the for row in rows loop. – Max Dec 23 '15 at 22:57
  • This does not appear to be a duplicate, as there are exactly 1 button for each Entry and the button is not passing the relevant Entry reference, or am I way off base? – Max Dec 23 '15 at 23:05
  • The statement **print Entry.get(entryid)** is not what you do to get the entry in a specific Entry widget. See the get examples at http://effbot.org/tkinterbook/entry.htm –  Dec 24 '15 at 01:04
  • Also partial is less confusing IMHO, **from functools import partial** and **e2 = Button(frame, text="Log Data "+str(row[0]), command=partial(saveData, e1))** will hopefully solve your problem. Note that you should always declare a function before you call it in a statement. You do the reverse in the above code. –  Dec 24 '15 at 01:17
  • Curly Joe, YOU are the MAN! That was it exactly. I moved the saveData above the for loop and used your construct for the button and it works perfectly. Also allows me to add additional elements that I will be including later for GPS coordinates. – Max Dec 24 '15 at 02:25