473,432 Members | 1,765 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,432 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 11814
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...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

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.