Tkinter Button command query

P

Paul A. Wilson

I'm new to Tkinter programming and am having trouble creating a
reusable button bar... I want to be able to feed my class a dictionary
of button names and function names, which the class will make.

My button bar is implemented a Frame subclass, which takes the button
dictionary as an argument and displays the buttons on the screen:

class OptionsBar(Frame):
def __init__(self, buttonDict, parent=None)
Frame.__init__(self, parent)
parent.someFunction() # This works fine
for (name, command) in buttonDict.items():
Button(self, text=name, command=command).pack(side=TOP,
fill=BOTH)

and then another Frame subclass, e.g. MyWindow, uses the bar as
follows:

self.buttonDict = {'Button1':'someFunction',
'Button2':'otherFunction'}
...
myBar = OptionsBar(parent=self, buttonDict=self.buttonDict)
myBar.pack(side=RIGHT)
...

def someFunction():
do button stuff

My problem is that the Button instances aren't calling the correct
functions when pressed. Is there anyway I get Button to call its
parent frame's parent frame's functions? I've tried using

self.buttonDict = {'Button1':'parent.someFunction',
'Button2':'parent.otherFunction'}

but to no avail. Hope my explanations make sense.

Any suggestions?

Cheers
PAW
 
P

Peter Otten

Paul said:
I'm new to Tkinter programming and am having trouble creating a
reusable button bar... I want to be able to feed my class a dictionary
of button names and function names, which the class will make.

My button bar is implemented a Frame subclass, which takes the button
dictionary as an argument and displays the buttons on the screen:

class OptionsBar(Frame):
def __init__(self, buttonDict, parent=None)
Frame.__init__(self, parent)
parent.someFunction() # This works fine
for (name, command) in buttonDict.items():
Button(self, text=name, command=command).pack(side=TOP,
fill=BOTH)

and then another Frame subclass, e.g. MyWindow, uses the bar as
follows:

self.buttonDict = {'Button1':'someFunction',
'Button2':'otherFunction'}
...
myBar = OptionsBar(parent=self, buttonDict=self.buttonDict)
myBar.pack(side=RIGHT)
...

def someFunction():
do button stuff

My problem is that the Button instances aren't calling the correct
functions when pressed. Is there anyway I get Button to call its
parent frame's parent frame's functions? I've tried using

self.buttonDict = {'Button1':'parent.someFunction',
'Button2':'parent.otherFunction'}

but to no avail. Hope my explanations make sense.

Any suggestions?

Use the function identifier directly instead of a string to identify the
commands, e. g:

import Tkinter
class OptionsBar(Tkinter.Frame):
def __init__(self, buttonDict, parent=None):
Tkinter.Frame.__init__(self, parent)
parent.someMethod() # This works fine only if parent is not None
for (name, command) in buttonDict.items():
Tkinter.Button(self, text=name,
command=command).pack(side=Tkinter.TOP,
fill=Tkinter.BOTH)

def aFunction():
print "a function"

class MyWindow(Tkinter.Frame):
def __init__(self, parent):
Tkinter.Frame.__init__(self, parent)
self.buttonDict = {'Button1': self.someMethod,
'Button2': aFunction}
#...
myBar = OptionsBar(parent=self, buttonDict=self.buttonDict)
myBar.pack(side=Tkinter.RIGHT)
#...

def someMethod(self):
print "some method"

root = Tkinter.Tk()
MyWindow(root).pack()
root.mainloop()

You can pass self.someMethod around as if it were a function. Python will
take care that the method is invoked with the instance denoted by self.

Note how I changed e. g. Button to Tkinter.Button. As you are already
creating reusable components you should also start to care about namespace
cluttering. If you are too lazy to type Tkinter in full beauty, use an
alias

import Tkinter as tk

and then tk.Button() etc.


Peter

PS: Do us - and yourself - the favour of using *4*-space indents. The more
people use it as a standard, the better you can tuck pieces of code from
different sources together.
 
F

Fredrik Lundh

Paul said:
I'm new to Tkinter programming and am having trouble creating a
reusable button bar... I want to be able to feed my class a dictionary
of button names and function names, which the class will make.

My button bar is implemented a Frame subclass, which takes the button
dictionary as an argument and displays the buttons on the screen:

class OptionsBar(Frame):
def __init__(self, buttonDict, parent=None)
Frame.__init__(self, parent)
parent.someFunction() # This works fine
for (name, command) in buttonDict.items():
Button(self, text=name, command=command).pack(side=TOP,
fill=BOTH)

Tkinter wants the functions, not the names of the functions. you can use
getattr() to get around this:

for (name, command) in buttonDict.items():
command = getattr(parent, command)
Button(self, text=name, command=command)...

(getattr(obj, "name") is the same as obj.name)

</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,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top