Search code examples
pythonbuttonlambdatkintertkinter-entry

How to set Entry.get as an argument of a command function with lambda in python Tkinter


I have an application that has a entry field and a button:

    from subprocess import *
    from Tkinter import *


    def remoteFunc(hostname):
            command = 'mstsc -v {}'.format(hostname)
            runCommand = call(command, shell = True)
            return

    app = Tk()
    app.title('My App')
    app.geometry('200x50+200+50')

    remoteEntry = Entry(app)
    remoteEntry.grid()

    remoteCommand = lambda x: remoteFunc(remoteEntry.get()) #First Option
    remoteCommand = lambda: remoteFunc(remoteEntry.get()) #Second Option

    remoteButton = Button(app, text = 'Remote', command = remoteCommand)
    remoteButton.grid()

    app.bind('<Return>', remoteCommand)

    app.mainloop()

and I want that when I insert an ip/computer name to the entry field it will sent it as a parameter to the command of the button, so when I press Return or pressing the button it will remote the computer with that name/ip.

When i execute this code with the first option (look at the code) it works only I press the Return key, and if I press the button this is the error:

Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1532, in __call__
return self.func(*args)
TypeError: <lambda>() takes exactly 1 argument (0 given)

If I try the second option of remoteCommand only if I try to press the button It work but I if press the Return key i get this error:

Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1532, in __call__
return self.func(*args)
TypeError: <lambda>() takes no arguments (1 given)

The only difference between the two is if lambda gets an argument or not.


Solution

  • The best solution in my opinion is to not use lambda. IMO, lambda should be avoided unless it really is the best solution to a problem, such as when a closure needs to be created.

    Since you want the same function to be called from a binding on the return key, and from the click of a button, write a function that optionally accepts an event, and then simply ignores it:

    For example:

    def runRemoteFunc(event=None):
        hostname = remoteEntry.get()
        remoteFunc(hostname)
    ...
    remoteButton = Button(..., command = remoteFunc)
    ...
    app.bind('<Return>', remoteCommand)