0

Answers from these questions: How to pass arguments to a Button command in Tkinter? and Why is Button parameter “command” executed when declared? are very much appreciated.

However, when I bind the button to automatically execute when the Enter key is pressed, it executes immediately. My code is:

from Tkinter import *

import ttk

from timeAttendance_show_DTR_GUI import * 


def employee_toShow(leftFrame,rightFrame):  

        empNumberToShow = '1'
        beginDateToShow = '2014-06-01'
        endDateToShow = '2014-06-31'
        requiredReport='dtr'

        emp = IntVar()  #please don't mind yet other parts as I am still working on them bit by bit.
        ttk.Label(leftFrame, text='Enter Employee Number').pack()
        emp_entry = ttk.Entry(leftFrame, textvariable=emp)
        emp_entry.pack()

        emp_DTR = ttk.Button(leftFrame, text='Calculate', command=lambda: indiv_DTR(rightFrame, empNumberToShow, beginDateToShow, endDateToShow, requiredReport))

        emp_entry.focus()
        emp_DTR.pack()
        root.bind('<Return>', indiv_DTR(rightFrame, empNumberToShow, \
            beginDateToShow, endDateToShow, requiredReport))  # This is where i get the problem


def indiv_DTR(frame, empNumberToShow, beginDateToShow, endDateToShow, requiredReport):

        dtr, absent, frequencyOfLate, frequencyOfUndertime, totalMinutesLate, totalMinutesUndertime, \
            frequencyOfGracePeriod, gracePeriodTotal = initialization(empNumberToShow, beginDateToShow, endDateToShow, requiredReport)

        tree = ttk.Treeview(frame, height=31)
        tree['show'] = 'headings'

        tree["columns"]=('Date', 'Day', 'AmIn', 'AM Out', 'PM In', 'PM Out', 'OT In', 'OT Out', 'Late', 'Early Out', 'Remarks')


        tree.column('Date', width=60)
        tree.column('Day', width=45 )
        tree.column('AmIn', width=50)
        tree.column('AM Out', width=50)
        tree.column('PM In', width=50)
        tree.column('PM Out', width=50)
        tree.column('OT In', width=50)
        tree.column('OT Out', width=50)
        tree.column('Late', width=50)
        tree.column('Early Out', width=65)
        tree.column('Remarks', width = 95)

        tree.heading('Date', text='Date')
        tree.heading("Day", text="Day")
        tree.heading("AmIn", text="AM In")
        tree.heading('AM Out', text='AM Out')
        tree.heading('PM In', text = 'PM In')
        tree.heading('PM Out', text = 'PM Out')
        tree.heading('OT In', text = 'OT In')
        tree.heading('OT Out', text='OT Out')
        tree.heading('Late', text='Late')
        tree.heading('Early Out', text='Early Out')
        tree.heading('Remarks', text='Remarks')

        for i in dtr:
            tree.insert("" , 'end', text= '', \
                values=(i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[7],i[8],i[9], i[10])) 
            tree.pack()

if __name__ == '__main__':

        employee_toShow(leftFrame,rightFrame)
        root.mainloop()

Obviously, just a newbie here (not even sure if my code indented correctly)... Any help will be much appreciated.

Miraj50
  • 4,257
  • 1
  • 21
  • 34
Inner Peace
  • 53
  • 1
  • 1
  • 7
  • Hint: see where the code says `lambda:` when setting up the `ttk.Button`? Notice how you made this change after reading those questions, so that the command would not happen immediately, but only when the button is clicked? Now. Notice how the code to bind the return key, in order to **run the same command**, **does not** currently have that `lambda:`? Notice how the problem is that the command happens immediately, and does not wait for the key to be pressed? In other words, **the same problem**, trying to set up **the same effect** - so did you **try the same workaround**? – Karl Knechtel Jan 06 '23 at 02:28

2 Answers2

2

When you call root.bind for <Return> you are passing the result of calling indiv_DTR(...) as a parameter. This is equivalent to the following:

res = indiv_DTR(rightFrame, empNumberToShow, beginDateToShow, endDateToShow, requiredReport)
root.bind('<Return>', res)

which should make it clearer that the function has already been executed.

To have the bind operation actually call this function you pass the method name. eg:

def onReturn(ev):
    # call the indiv_DTR function

root.bind('<Return>', onReturn)

Or you can provide a lambda expression if you need some local variables to be captured as parameters to the event handler.

patthoyts
  • 32,320
  • 3
  • 62
  • 93
2

Please read about posting minimal code.

In this case

    root.bind('<Return>', indiv_DTR(rightFrame, empNumberToShow,
              beginDateToShow, endDateToShow, requiredReport))

calls indiv_DTR immediately because that is what you say to do! To delay the call, you need to do the same thing you did in the Button call: prefix with lambda :. However, to actually 'execute the Button', which should mean to invoke its callback as if the button were pressed, you should use the .invoke method.

    root.bind('<Return>', emp_DTR.invoke)

(Notice, not emp_DTR.invoke()). This way, if you change the indiv_DTR arguments in the Button call, you will not have to remember to change them in the bind call.

A third option would be to define the callback first

def callback():
    return indiv_DTR(rightFrame, empNumberToShow,
              beginDateToShow, endDateToShow, requiredReport)

and then pass callback to both the Button and bind calls. I generally define callbacks first even when I will only pass them once to one widget constructor, unless the return expression is really short.

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52