473,320 Members | 1,695 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Arguments for button command via Tkinter?

Recently, I have been needing to do this alot and I can never find a
way around it, the main reason I want to do this is because for example
in the application I am making right now, it creates a grid of buttons
in a loop and they all have the same purpose so they need to call the
same method, within this method they need to change the background
color of the button clicked, I've tried stuff like...

button['command'] = lambda: self.fill(button)

def fill(self, wid):
button['bg'] = '#ff0000'

But that's no good, everytime it I do click a button the lambda method
I have setup keeps getting recreated so all of the button commands
point to the same lambda method, I have also tried appending them to an
array, and calling them from that.

Anyone have any clue as of what to do? Thanks.

Oct 31 '05 #1
8 11809
And yet the stupidity continues, right after I post this I finnally
find an answer in a google search, It appears the way I seen it is to
create a class for each button and have it call the method within that.
If anyone else has any other ideas please tell.

Oct 31 '05 #2
da****@gmail.com wrote:
And yet the stupidity continues, right after I post this I finnally
find an answer in a google search, It appears the way I seen it is to
create a class for each button and have it call the method within that.
If anyone else has any other ideas please tell.

I'm hoping you have simply mis-stated your correct understanding of the
problem, and that what you really propose to do is create a button class
of which each button in your interface is an instance.

Let's suppose you want each button to toggle between two colors, but
that the colors for each button are different. The thing to do is create
a button class that subclasses the button class of your GUI package
(whatever that may be), storing the required color values as instance
attributes.

In wxPython, for example, I would write something like (warning: untested):

import wx

class myButton(wx.Button):

def __init__(self, color1, color2, *args, **kw):
wx.Button.__init__(self, *args, **kw)
self.c1 = color1
self.c2 = color2
self.state = False

def onClick(self, event):
if self.state:
self.SetBackgroundColor(self.c1)
else:
self.SetBaclgroundColor(self.c2)
self.state = not self.state

Then when you create a button with, say,

but1 = myButton(wx.RED, wx.BLUE, ...)

you can associate a click on that button with a bound instance method,
which you'd do in wxPython like:

wx.EVT_BUTTON(parent, but1, but2.onClick)

but similar considerations apply to Tkinter, and you appear to have the
wit to be able to extend the argument to that toolkit.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Oct 31 '05 #3
Il Mon, 31 Oct 2005 06:23:12 -0800, da****@gmail.com ha scritto:
And yet the stupidity continues, right after I post this I finnally
find an answer in a google search, It appears the way I seen it is to
create a class for each button and have it call the method within that.
If anyone else has any other ideas please tell.


This is how I do it: Supposing I have three buttons b1, b2 and b3, and I
want for each button to call the same callback with, as argument, the
button itself:
def common_callback(button):
# callback code here
class CallIt(objetc):
def __init__(function, *args ):
self.function, self.args = function, args
def __call__(self, *ignore):
self.function(button, *self.args)

b1['command']= CallIt(common_callback, b1)
b2['command']= CallIt(common_callback, b2)
b3['command']= CallIt(common_callback, b3)

This way you need only one class (a sort of custom callable) and
its instances gets called by Tkinter and in turn calls your
callback with the proper arguments.

Ciao
-----
FB

Oct 31 '05 #4
"da****@gmail.com" <da****@gmail.com> writes:
Recently, I have been needing to do this alot and I can never find a
way around it, the main reason I want to do this is because for example
in the application I am making right now, it creates a grid of buttons
in a loop and they all have the same purpose so they need to call the
same method, within this method they need to change the background
color of the button clicked, I've tried stuff like...

button['command'] = lambda: self.fill(button)

def fill(self, wid):
button['bg'] = '#ff0000'

But that's no good, everytime it I do click a button the lambda method
I have setup keeps getting recreated so all of the button commands
point to the same lambda method, I have also tried appending them to an
array, and calling them from that.

Anyone have any clue as of what to do? Thanks.


People have pointed out how to do this with a class, but you can do it
with lambdas as well. I suspect the problem you're having is that
python is binding values at call time instead of at definition time,
but it's hard to tell without more of your source code.

If I'm right, one solution is to make the values you want bound at
definition time optional arguments to the lambda, bound to the correct
value then. So you'd do:

button['command'] = lambda b = button: self.fill(b)

The version you used will look up the name button when the lambda is
invoked. My version will look it up when the lambda is defined.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Oct 31 '05 #5
Yah, thats how i learned how to do it, thanks.

Oct 31 '05 #6
Francesco Bochicchio wrote:
Il Mon, 31 Oct 2005 06:23:12 -0800, da****@gmail.com ha scritto:

And yet the stupidity continues, right after I post this I finnally
find an answer in a google search, It appears the way I seen it is to
create a class for each button and have it call the method within that.
If anyone else has any other ideas please tell.

This is how I do it: Supposing I have three buttons b1, b2 and b3, and I
want for each button to call the same callback with, as argument, the
button itself:
def common_callback(button):
# callback code here
class CallIt(objetc):
def __init__(function, *args ):
self.function, self.args = function, args
def __call__(self, *ignore):
self.function(button, *self.args)

b1['command']= CallIt(common_callback, b1)
b2['command']= CallIt(common_callback, b2)
b3['command']= CallIt(common_callback, b3)

This way you need only one class (a sort of custom callable) and
its instances gets called by Tkinter and in turn calls your
callback with the proper arguments.

I don't see why this is preferable to having the callback as a bound
method of the button instances. What's the advantage here? It looks
opaque and clunky to me ...

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Oct 31 '05 #7


Steve Holden wrote:
Francesco Bochicchio wrote:
Il Mon, 31 Oct 2005 06:23:12 -0800, da****@gmail.com ha scritto:

And yet the stupidity continues, right after I post this I finnally
find an answer in a google search, It appears the way I seen it is to
create a class for each button and have it call the method within that.
If anyone else has any other ideas please tell.


This is how I do it: Supposing I have three buttons b1, b2 and b3, and I
want for each button to call the same callback with, as argument, the
button itself:
def common_callback(button):
# callback code here
class CallIt(objetc):
def __init__(function, *args ):
self.function, self.args = function, args
def __call__(self, *ignore):
self.function(button, *self.args)

b1['command']= CallIt(common_callback, b1)
b2['command']= CallIt(common_callback, b2)
b3['command']= CallIt(common_callback, b3)

This way you need only one class (a sort of custom callable) and
its instances gets called by Tkinter and in turn calls your
callback with the proper arguments.

I don't see why this is preferable to having the callback as a bound
method of the button instances. What's the advantage here? It looks
opaque and clunky to me ...


I'm not sure on the advantage either. I just recently started handling
my buttons with button id's.

def __init__(self, *args, **kwds):
...

b1 = Tk.Button( frame, text=button,
command=self.command(button) )
...

The button label is used as the id above, but a number or code could
also be used.

def command(self, id):
""" Assign a command to an item.
The id is the value to be returned.
"""
def do_command():
self.exit(event=id)
return do_command

In this case it's a dialog button so it calls the exit method which sets
self.return to the button id before exiting.

Cheers,
Ron
Oct 31 '05 #8
Il Mon, 31 Oct 2005 19:23:18 +0000, Steve Holden ha scritto:
Francesco Bochicchio wrote:
Il Mon, 31 Oct 2005 06:23:12 -0800, da****@gmail.com ha scritto:

And yet the stupidity continues, right after I post this I finnally
find an answer in a google search, It appears the way I seen it is to
create a class for each button and have it call the method within that.
If anyone else has any other ideas please tell.

This is how I do it: Supposing I have three buttons b1, b2 and b3, and I
want for each button to call the same callback with, as argument, the
button itself:
def common_callback(button):
# callback code here
class CallIt(objetc):
def __init__(function, *args ):
self.function, self.args = function, args
def __call__(self, *ignore):
self.function(button, *self.args)

b1['command']= CallIt(common_callback, b1)
b2['command']= CallIt(common_callback, b2)
b3['command']= CallIt(common_callback, b3)

This way you need only one class (a sort of custom callable) and
its instances gets called by Tkinter and in turn calls your
callback with the proper arguments.

I don't see why this is preferable to having the callback as a bound
method of the button instances. What's the advantage here? It looks
opaque and clunky to me ...

regards
Steve


I'm not saying that my method is better or even 'preferable'. Just
different.

The reason I came up this approach (years ago) is because I was used to
other toolkits that always pass the widget as argument of the callback. So
this was a fast solution to 'normalize' Tkinter with respect to what I
perceived (and still do) as a limitation. As a bonus, you can also pass to
the callback as many other arguments as you want.
Another reason is that my basic approach to coding GUI is to use a class
for each window. To put the code to handle button callbacks in a separate
class feels to me a bit too much dispersive and potentially cumbersome if
callback code has to interact with other window elements (although in
Python nothing is impossible).

Ciao
-----
FB
why I sometime

Nov 1 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: mksql | last post by:
New to Tkinter. Initially, I had some code that was executing button commands at creation, rather than waiting for user action. Some research here gave me a solution, but I am not sure why the...
2
by: Paul A. Wilson | last post by:
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....
6
by: Elaine Jackson | last post by:
I've got a script where a button gets pushed over and over: to cut down on the carpal tunnel syndrome I'd like to have the button respond to presses of the Enter key as well as mouse clicks; can...
3
by: Shankar Iyer (siyer | last post by:
Hi, I have another Tkinter-related question. At the beginning of my program, a tkinter window is created with six buttons. Each of these buttons is assigned a function that should be executed...
8
by: Jay | last post by:
I'm having a problem using lambda to use a command with an argument for a button in Tkinter. buttons = range(5) for x in xrange(5): buttons = Button(frame, text=str(x+1), command=lambda:...
5
by: vagrantbrad | last post by:
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...
5
by: Kevin Walzer | last post by:
I'm having difficulty structuring a Tkinter menu entry. Here is the command in question: self.finkmenu.add_command(label='Update List of Packages',...
2
by: Bellum | last post by:
I'm rather new to both Tkinter and Classes, so whatever I'm doing wrong probably seems really stupid. Just bare with me, here. The reference to the buttons seems to disappear after the __init__...
1
by: AdamGr | last post by:
Using tkinter, how does one add arguments to functions called by buttons? For example I have the line: b = Button(parent, command = self.login) but what if self.login has parameters, like...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.