By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,732 Members | 1,435 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,732 IT Pros & Developers. It's quick & easy.

Tkinter button not working as expected

P: n/a
I've created a short test program that uses tkFileDialog.askdirectory
to help the user input a path into a tk entry widget. The problem I'm
having is that when I run the code as listed below, the getPath
function is called when the program initially runs, not when the button
is pressed.

from Tkinter import *
import tkFileDialog

class App:

def __init__(self, master):

frame = Frame(master)
frame.pack()

t = StringVar()
self.entry = Entry(frame, textvariable=t)
self.entry.pack(side=LEFT)

self.button = Button(frame, text="Select", fg="red")
self.button["command"] = self.getPath(t)
self.button.pack(side=LEFT)

def getPath(self, t):
dirPath = tkFileDialog.askdirectory(initialdir="c:\\")
print dirPath
t.set(dirPath)

root = Tk()
app = App(root)
root.mainloop()
The problem arises when I try to pass the t variable in the "command"
option of the button widget. If I set the command to
"command=self.getpath" rather than "command=self.getpath(t)", then I
don't get this issue. But I would like to be able to pass a variable
to the the function through the command option. I'm a Tk newbie ....
what am I doing wrong?

Sep 21 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
va*********@yahoo.com wrote:
I've created a short test program that uses tkFileDialog.askdirectory
to help the user input a path into a tk entry widget. The problem I'm
having is that when I run the code as listed below, the getPath
function is called when the program initially runs, not when the button
is pressed.
[...]
what am I doing wrong?
Recently I've done a stupid error with a callback (probably I was
sleeping), so I try again. Note many little changes that I belive
improve your program:

import Tkinter as tk
import tkFileDialog

class App(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.pack()

self.entrytxt = tk.StringVar()
entry = tk.Entry(self, textvariable=self.entrytxt)
entry.pack(side=tk.LEFT)

button = tk.Button(self, text="Select", fg="red",
command=self.getPath)
button.pack(side=tk.LEFT)

def getPath(self):
dirPath = tkFileDialog.askdirectory(initialdir="c:/")
self.entrytxt.set(dirPath)
print dirPath

root = tk.Tk()
app = App(root)
root.mainloop()

Bye,
bearophile

Sep 21 '06 #2

P: n/a
va*********@yahoo.com wrote:
I've created a short test program that uses tkFileDialog.askdirectory
to help the user input a path into a tk entry widget. The problem I'm
having is that when I run the code as listed below, the getPath
function is called when the program initially runs, not when the button
is pressed.

from Tkinter import *
import tkFileDialog

class App:

def __init__(self, master):

frame = Frame(master)
frame.pack()

t = StringVar()
self.entry = Entry(frame, textvariable=t)
self.entry.pack(side=LEFT)

self.button = Button(frame, text="Select", fg="red")
self.button["command"] = self.getPath(t)
self.button.pack(side=LEFT)

def getPath(self, t):
dirPath = tkFileDialog.askdirectory(initialdir="c:\\")
print dirPath
t.set(dirPath)

root = Tk()
app = App(root)
root.mainloop()
The problem arises when I try to pass the t variable in the "command"
option of the button widget. If I set the command to
"command=self.getpath" rather than "command=self.getpath(t)", then I
don't get this issue. But I would like to be able to pass a variable
to the the function through the command option. I'm a Tk newbie ....
what am I doing wrong?
Well, in python 2.5, you might consider functools.partial.

Other options, including lambda, will be suggested and are the
traditional way to do this sort of thing.

Here is the revised code:

import functools
from Tkinter import *
import tkFileDialog

class App:

def __init__(self, master):

frame = Frame(master)
frame.pack()

t = StringVar()
self.entry = Entry(frame, textvariable=t)
self.entry.pack(side=LEFT)

self.button = Button(frame, text="Select", fg="red")

# note change here
self.button["command"] = functools.partial(self.getPath, t)
self.button.pack(side=LEFT)

def getPath(self, t):
dirPath = tkFileDialog.askdirectory(initialdir="c:\\")
print dirPath
t.set(dirPath)

root = Tk()
app = App(root)
root.mainloop()


--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
Sep 21 '06 #3

P: n/a
va*********@yahoo.com wrote:
I've created a short test program that uses tkFileDialog.askdirectory
to help the user input a path into a tk entry widget. The problem I'm
having is that when I run the code as listed below, the getPath
function is called when the program initially runs, not when the button
is pressed.
the right side of an assignment is always evaluated before it is assigned, so

self.button["command"] = self.getPath(t)

will call self.getPath(t) and then assign the return value to button["command"].
quite obvious, if you think about it, right ?

the easiest way to fix this is to add a local function that calls getPath, and
use that as the button callback:

def callback():
self.getPath(t)
self.button["command"] = callback

(if you want, you can inline the getPath code in the callback).

</F>

Sep 22 '06 #4

P: n/a
Thank you Fredrik. It makes total sense now that you've explained it
this way. I frustrated at my ignorance on the assignment issue :)


Fredrik Lundh wrote:
va*********@yahoo.com wrote:
I've created a short test program that uses tkFileDialog.askdirectory
to help the user input a path into a tk entry widget. The problem I'm
having is that when I run the code as listed below, the getPath
function is called when the program initially runs, not when the button
is pressed.

the right side of an assignment is always evaluated before it is assigned, so

self.button["command"] = self.getPath(t)

will call self.getPath(t) and then assign the return value to button["command"].
quite obvious, if you think about it, right ?

the easiest way to fix this is to add a local function that calls getPath, and
use that as the button callback:

def callback():
self.getPath(t)
self.button["command"] = callback

(if you want, you can inline the getPath code in the callback).

</F>
Sep 22 '06 #5

P: n/a
va*********@yahoo.com wrote:
Thank you Fredrik. It makes total sense now that you've explained it
this way. I frustrated at my ignorance on the assignment issue :)
well, it's one of those "you'll only do this once" mistakes that
*everyone* does (mutable default arguments and unexpected integer
division are two of the others).

it's the "I'm always doing this" mistakes that are really frustrating
(for me, "'str' object has no attribute 'startwith'" is at the top of
that list...)

</F>

Sep 24 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.