Newbie alert !

Adam DePrince adam at cognitcorp.com
Fri Dec 3 15:10:06 CET 2004


>  
> > bou_europe=Button(fen1, text='Europe',\
> >                    command=rings(41, 100, -22, 'blue'))

Silly me.  I misunderstood what you wanted first time around.  

In Python functions are "first class objects" that are treated no
differently than anything else.  When you setup your button you
executing the function rings, taking its return value (None) and asking
command to call it when the button is clicked.  

Look at the following code for illustration:

def call_and_print( parameter ):
	print parameter()

def myfunction( ):
	return "abc"

>>>call_and_print( myfunction )
abc
>>>call_and_print( myfunction() )
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in call_and_print
TypeError: 'str' object is not callable

Now, your function rings returns None, which is similarly not callable. 
Tk has the good manners to ignore your exception and move on.  

What you want to do is pass a function as a parameter.  rings mustn't be
the function that draws the ring, rather it must return a function that
draws your ring.  

There are several ways of doing this.  You can use lambda as somebody
else suggested.  My prefered way of doing this is to use python's
optional parameter mechanism.  Look at this code first:

def number_generator( number ):
    def func_to_return( num=number ):
        return num

    return func_to_return

make_a_10 = number_generator( 10 )
make_a_20 = number_generator( 20 )

# Now call ...

print make_a_10
print make_a_20

print make_a_10( )
print make_a_20( )
print make_a_10( )
print make_a_20( )
print make_a_10( )
print make_a_20( )

When run ... 

<function func_to_return at 0xf6f36994>
<function func_to_return at 0xf6f369cc>
10
20
10
20
10
20

Now, to make your program work, we make a small change to rings and
nothing else ... 

def rings(size,offsetX,offsetY,coul):
     def internal_rings(size=size,
                        offsetX=offsetX,
                        offsetY=offsetY,
                        coul=coul):
          x1,y1,x2,y2 = 170, 103, 170, 103,
          can1.create_oval(x1-size-offsetX,y1+size+offsetY,\
                           x2+size-offsetX,y2-size+offsetY,\
                           width=8, outline=coul)
     return internal_rings

Of course, you could say ... 

...internal_rings(size=size,offsetX=offsetX...
but that would mean that I must argue with my mail client.

Enjoy!


> > bou_europe.pack( )
> > 
> > bou_asia=Button(fen1, text='Asia',\
> >                    command=rings(size=41, offsetX=50,offsetY=22, 
> > coul='yellow'))
> > bou_asia.pack( )
> > 
> > bou_africa=Button(fen1, text='Africa',\
> >                    command=rings(size=41, offsetX=0,offsetY=-22, 
> > coul='black'))
> > bou_africa.pack( )
> > 
> > bou_australia=Button(fen1, text='Australia',\
> >                    command=rings(size=41, offsetX=-50,offsetY=22, 
> > coul='dark green'))
> > bou_australia.pack( )
> > 
> > bou_america=Button(fen1, text='America',\
> >                    command=rings(size=41, offsetX=-100,offsetY=-22, 
> > coul='Red'))
> > bou_america.pack( )
> > 
> > bou_quit=Button(fen1, text='Quit', command=fen1.quit)
> > bou_quit.pack(side=BOTTOM)
> > 
> > fen1.mainloop()
> > fen1.destroy()
> > 
> > </CODE>
> > 
> > I just cannot figure out why the rings are draw right from the start and 
> >   don't wait for their buttons to be pressed before being drawn :  I've 
> > written similar functions before to draw lines, rectangles and whatever 
> > else with success.
> 
> Because Button creates a button on the screen and moves on.  Would it be
> correct to say that you want the program to block on the creation of
> each button until it was pressed?
> 
> Typically, GUI's rely on the notion of a callback.  You create a widget,
> assign some function to be called when something happens and then enter
> your "mainloop" where you wait.  If you want your rings to be created
> with button presses then you should be creating them in the button
> callbacks ... 
> 
> - Adam
> > 
> > Using Python 2.3, IDLE and Win2k.
> > 
> > Thanks for your time
> > 
> > Jean Montambeault
> Adam DePrince 

Adam DePrince 





More information about the Python-list mailing list