Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Two naive Tkinter questions

Reply
Thread Tools

Two naive Tkinter questions

 
 
Andrew Koenig
Guest
Posts: n/a
 
      11-02-2003
from Tkinter import *

class Application(Frame):

def setcolor(self):
self["bg"] = "blue"

def createWidgets(self):
self.b1 = Button(self, bg = "red", command = self.setcolor)
self.b1.place(height = 50, width = 50)

self.b2 = Button(self, text = "Exit", command = self.quit)
self.b2.place(height = 50, width = 50, x = 50)

def __init__(self, master=None):
Frame.__init__(self, master)
self.place(height = 50, width = 100)
self.createWidgets()

app = Application()
app.mainloop()


1) When I run this program, it displays two buttons. When I click the
button on the left, I would like the color of that button to change from red
to blue. This code is obviously the wrong way to accomplish this, because
when setcolor is called, it gets the button's parent, not the button itself.
How do I arrange for setcolor to get the right object?

2) The window in which these buttons appear is the wrong size, and does not
depend on the height and width given to self.place in __init__. Yet the
height and width arguments do something, because if I set width to 75, it
cuts off half the right-hand button. How do I say how large I want the
window to be?


 
Reply With Quote
 
 
 
 
Martin v. =?iso-8859-15?q?L=F6wis?=
Guest
Posts: n/a
 
      11-02-2003
"Andrew Koenig" <> writes:

> 1) When I run this program, it displays two buttons. When I click the
> button on the left, I would like the color of that button to change from red
> to blue. This code is obviously the wrong way to accomplish this, because
> when setcolor is called, it gets the button's parent, not the button itself.
> How do I arrange for setcolor to get the right object?


In the specific example, you could just *know* that setcolor deals
with self.b1. In the more general example, you can create dynamic
callback functions:

self.b1 = Button(self, bg = "red",
command = lambda: self.b1.config(bg="blue"))

This uses a number of tricks: the lambda function has no arguments,
yet it uses self - so it is a nested function. Also, inside a lambda
function, you can have only expressions, so self.b1['bg']='blue' would
not be allowed. In the general case, and not assuming nested
functions, you would write

def createWidgets(self):
def b1_setcolor(self=self):
self.b1['bg']='blue'
self.b1 = Button(self, bg = "red", command=b1_setcolor)

> 2) The window in which these buttons appear is the wrong size, and does not
> depend on the height and width given to self.place in __init__. Yet the
> height and width arguments do something, because if I set width to 75, it
> cuts off half the right-hand button. How do I say how large I want the
> window to be?


The problem is that there is another toplevel widget around your
frame; the frame itself has the size you have specified. You could
either use Toplevel instead of Frame as a base, or you could adjust
the size of the root window, e.g. through

app.master.wm_geometry("100x50")

HTH,
Martin

 
Reply With Quote
 
 
 
 
Andrew Koenig
Guest
Posts: n/a
 
      11-02-2003
> In the specific example, you could just *know* that setcolor deals
> with self.b1. In the more general example, you can create dynamic
> callback functions:
>
> self.b1 = Button(self, bg = "red",
> command = lambda: self.b1.config(bg="blue"))
>
> This uses a number of tricks: the lambda function has no arguments,
> yet it uses self - so it is a nested function. Also, inside a lambda
> function, you can have only expressions, so self.b1['bg']='blue' would
> not be allowed. In the general case, and not assuming nested
> functions, you would write
>
> def createWidgets(self):
> def b1_setcolor(self=self):
> self.b1['bg']='blue'
> self.b1 = Button(self, bg = "red", command=b1_setcolor)


I worked out something similar, but I must confess that it appears
needlessly complicated. I was hoping for a simpler solution, such as a
variation of the "command" attribute that would cause its associated
argument to be called with the button rather than its parent.

Your first suggestion, knowing that setcolor deals with self.b1, doesn't
work with my application because I'm going to have lots of these buttons,
and I want to be able to set their colors independently.

>
> > 2) The window in which these buttons appear is the wrong size, and does

not
> > depend on the height and width given to self.place in __init__. Yet the
> > height and width arguments do something, because if I set width to 75,

it
> > cuts off half the right-hand button. How do I say how large I want the
> > window to be?

>
> The problem is that there is another toplevel widget around your
> frame; the frame itself has the size you have specified. You could
> either use Toplevel instead of Frame as a base, or you could adjust
> the size of the root window, e.g. through
>
> app.master.wm_geometry("100x50")


Gotcha -- thanks.


 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      11-02-2003
Andrew Koenig wrote:

> work with my application because I'm going to have lots of these buttons,
> and I want to be able to set their colors independently.


If you have many buttons with similar functionality, I'd suggest using a
subclass, e. g.:

import Tkinter as tk

class ColorButton(tk.Button):
def __init__(self, master, text, color):
tk.Button.__init__(self, master, text=text, command=self.execute)
self.color = color
def execute(self):
self["background"] = self.color


root = tk.Tk()
for color in "red green blue yellow".split():
ColorButton(root, text=color.capitalize(), color=color).pack()
root.mainloop()

Peter
 
Reply With Quote
 
Alan Gauld
Guest
Posts: n/a
 
      11-03-2003
On Sun, 02 Nov 2003 21:32:12 GMT, "Andrew Koenig" <>
wrote:
> Your first suggestion, knowing that setcolor deals with self.b1, doesn't
> work with my application because I'm going to have lots of these buttons,
> and I want to be able to set their colors independently.


A slight variant on the technique using lambda is:

def setcolor(self,widget=self):
widget['bg']='blue'
def createWidgets(self):
self.b1 = Button(self, bg = "red",
command=lambda: self.setcolor(self.b1))

Here we use the lambda to call the setcolor method with
the widget parameter and use that within the setcolor method.

This way you keep one method but call it from several places.
The downside is you introduce an extra function call, but in
a GUI event handler that's not going to be a problem!

HTH,

Alan G.




Author of the Learn to Program website
http://www.freenetpages.co.uk/hp/alan.gauld
 
Reply With Quote
 
Martin Franklin
Guest
Posts: n/a
 
      11-03-2003
On Sun, 2003-11-02 at 21:32, Andrew Koenig wrote:
> > In the specific example, you could just *know* that setcolor deals
> > with self.b1. In the more general example, you can create dynamic
> > callback functions:
> >
> > self.b1 = Button(self, bg = "red",
> > command = lambda: self.b1.config(bg="blue"))
> >
> > This uses a number of tricks: the lambda function has no arguments,
> > yet it uses self - so it is a nested function. Also, inside a lambda
> > function, you can have only expressions, so self.b1['bg']='blue' would
> > not be allowed. In the general case, and not assuming nested
> > functions, you would write
> >
> > def createWidgets(self):
> > def b1_setcolor(self=self):
> > self.b1['bg']='blue'
> > self.b1 = Button(self, bg = "red", command=b1_setcolor)

>
> I worked out something similar, but I must confess that it appears
> needlessly complicated. I was hoping for a simpler solution, such as a
> variation of the "command" attribute that would cause its associated
> argument to be called with the button rather than its parent.
>
> Your first suggestion, knowing that setcolor deals with self.b1, doesn't
> work with my application because I'm going to have lots of these buttons,
> and I want to be able to set their colors independently.
>



For this I would use a callback class and it's __call__ method

(untested)

class Callback:
def __init__(self, button, colour):
self.button = button
self.colour = colour


def __call__(self):
self.button.config(background = self.colour)





self.b1 = Button(self, background = "red")
self.b1.config(command = Callback(self.b1, "blue"))
self.b1.pack(.....)



Regards
Martin


--
Martin Franklin <>


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Naive idiom questions Terran Melconian Python 10 02-02-2008 05:55 PM
Naive threading performance questions Worky Workerson Perl Misc 15 10-31-2006 04:04 AM
Naive question: Crystal reports in ASP.NET =?Utf-8?B?a2Q=?= ASP .Net 1 05-28-2005 02:23 PM
Setting up my website - mod_ruby and Apache V2 - Naive questions. Victor Reyes Ruby 5 09-15-2004 07:54 PM
2 naive questions: Perl 6; Perl vs. shell scripts J Krugman Perl Misc 7 06-14-2004 02:14 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57