473,586 Members | 2,707 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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(butto n)

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 11828
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.co m 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.But ton):

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

def onClick(self, event):
if self.state:
self.SetBackgro undColor(self.c 1)
else:
self.SetBaclgro undColor(self.c 2)
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(p arent, 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.co m 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__(functi on, *args ):
self.function, self.args = function, args
def __call__(self, *ignore):
self.function(b utton, *self.args)

b1['command']= CallIt(common_c allback, b1)
b2['command']= CallIt(common_c allback, b2)
b3['command']= CallIt(common_c allback, 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.c om" <da****@gmail.c om> 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(butto n)

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.or g> 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.co m 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__(functi on, *args ):
self.function, self.args = function, args
def __call__(self, *ignore):
self.function(b utton, *self.args)

b1['command']= CallIt(common_c allback, b1)
b2['command']= CallIt(common_c allback, b2)
b3['command']= CallIt(common_c allback, 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.co m 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__(functi on, *args ):
self.function, self.args = function, args
def __call__(self, *ignore):
self.function(b utton, *self.args)

b1['command']= CallIt(common_c allback, b1)
b2['command']= CallIt(common_c allback, b2)
b3['command']= CallIt(common_c allback, 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.co mmand(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.co m 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__(functi on, *args ):
self.function, self.args = function, args
def __call__(self, *ignore):
self.function(b utton, *self.args)

b1['command']= CallIt(common_c allback, b1)
b2['command']= CallIt(common_c allback, b2)
b3['command']= CallIt(common_c allback, 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
3998
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 extra step is necessary. This causes the "graph" function to execute when the button is created: Button(root, text='OK', command=graph(canvas))) ...
2
3236
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. My button bar is implemented a Frame subclass, which takes the button dictionary as an argument and displays the buttons on the screen: class...
6
6078
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 somebody clue me in regarding how this is done? Muchas gracias. Peace
3
1800
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 only when the button is pressed. However, it seems that these functions are all executed once when the button widgets are first created. Why is this...
8
8115
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: self.highlight(x)) buttons.pack(side=LEFT) The buttons are correctly numbered 1 through 5, but no matter which
5
5980
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 getPath function is called when the program initially runs, not when the button is pressed. from Tkinter import * import tkFileDialog class...
5
2550
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', command=self.authorizeCommand(self.scanPackages)) When I start my program, it crashes because it's trying to run the command self.authorizeCommand. The reason I'm structuring it in this...
2
1680
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__ method, so when I try to call them and change them in another method, I get an attribute error. def __init__(self): self.window = Tk() ...
1
1388
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 requiring a username parameter and password parameter? commands called by buttons, or any tkinter object, don't seem to have any way to send arguments to...
0
7839
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8202
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8338
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
8216
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6614
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, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5710
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3865
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2345
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1449
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.