Tkinter button not working as expected

V

vagrantbrad

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?
 
B

bearophileHUGS

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
 
J

James Stroud

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/
 
F

Fredrik Lundh

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>
 
V

vagrantbrad

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 said:
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>
 
F

Fredrik Lundh

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>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top