Dorian Dore
Dorian Dore

Reputation: 962

functools.partial doesn't pass Tkinter argument

I am creating an application that requires input from the user. The code has an entry widget, and there is a button that calls a function with the input from one of the entry widgets as an argument. However, whenever I print the argument (the content of the entry widget) I get an empty list instead of what I entered.

#!/usr/bin/env python

import grammar 
import shelve
from functools import partial
from Tkinter import *
def call_response(text):
    print text
    grammar.analyze.analyze(text)

class MainWindow(Tk):
    def new_object(self):
        main_frame = Frame(self)
        bottom_frame = Frame(self)
        main_frame.pack()
        bottom_frame.pack(side=BOTTOM)
        output = Text(main_frame)
        output.pack()
        input_entry = Entry(bottom_frame, width=50)
        input_entry.grid(row=1, column=1)
        send_input_button = Button(bottom_frame, text='Chat!', command=partial(
             call_response, input_entry.get().split()))
        send_input_button.grid(row=1, column=2)
        mainloop()

root = MainWindow()
root.new_object()

Does anyone know what could be causing this to happen, or what might be wrong with my code?

Upvotes: 1

Views: 983

Answers (3)

user4171906
user4171906

Reputation:

call_response should be part of the class IMHO which eliminates the problems.

    self.input_entry = Entry(bottom_frame, width=50)
    send_input_button = Button(bottom_frame, text='Chat!', command=self.call_response)

def call_response(self):
    text=self.input_entry.get().split()
    grammar.analyze.analyze(text)

Upvotes: 3

Joran Beasley
Joran Beasley

Reputation: 114038

or just change it to

def call_response(text_fn):
    text = text_fn().split()
    print text
    grammar.analyze.analyze(text)
....

      send_input_button = Button(bottom_frame, text='Chat!', command=partial(
         call_response, input_entry.get))

as an alternative if you really want to avoid lambda ... but lambda is fine @AlexMarteli has valid criticism of it ... but for something simple like this they work fine

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1123940

You fetch the entry once, when creating the button; a partial() does not execute the expressions you used to create the arguments when it itself is called; the input_entry.get().split() expression is executed first, and the result is passed to the partial() object being created.

Use a lambda here to have the entry.get() executed when the button is clicked:

send_input_button = Button(bottom_frame, text='Chat!', command=lambda:
     call_response(input_entry.get().split()))

Upvotes: 3

Related Questions