Newbie alert !

  • Thread starter Jean Montambeault
  • Start date
J

Jean Montambeault

I am not only learning Python but programming itself ; reading your
posts makes me believe that nobody is that much of a beginner here. Is
there a newgroup or list for my type somewhere I can't find it ?

To illustrate my case this script :

<CODE>

# function to draw rings for an Olympic flag
def rings(size,offsetX,offsetY,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)

# **main****main****main****main****main****main**

fen1=Tk()
can1=Canvas(fen1, bg='white', height=206, width=340)
can1.pack(side=LEFT)

bou_europe=Button(fen1, text='Europe',\
command=rings(41, 100, -22, 'blue'))
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.

Using Python 2.3, IDLE and Win2k.

Thanks for your time

Jean Montambeault
 
J

Jean Montambeault

.... at the start of the file.
I just thought it to be too obvious to be included : my mistake.

Thanks

Jean
 
S

Simon Brunning

I am not only learning Python but programming itself ; reading your
posts makes me believe that nobody is that much of a beginner here. Is
there a newgroup or list for my type somewhere I can't find it ?

The tutor mailing list might be just the place -
To illustrate my case this script :

(Snip)

Sorry, I'm not much of a GUI programmer...
 
E

Eric Brunel

Jean said:
I am not only learning Python but programming itself ; reading your
posts makes me believe that nobody is that much of a beginner here. Is
there a newgroup or list for my type somewhere I can't find it ?

To illustrate my case this script :

<CODE>

# function to draw rings for an Olympic flag
def rings(size,offsetX,offsetY,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)

# **main****main****main****main****main****main**

fen1=Tk()
can1=Canvas(fen1, bg='white', height=206, width=340)
can1.pack(side=LEFT)

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

Here is what you do here: you *call* your "rings" function with the given
parameters, and you assign the *result* of the function (which is None, since
you do not have any "return" statement in rings) to the "command" option of your
button. Since you do that for all buttons, all circles are drawn right away and
no command is attached to any of your buttons.

The basic solution would be to create 5 different functions - one for each ring
- and assign the function to the button's command option:

def ringEurope():
rings(41, 100, -22, 'blue')
bou_europe = Button(fen1, text='Europe', command=ringEurope)

And so on...

Another shorter, but more difficult to understand solution would be to use an
anonymous function built with lambda. Here is how it goes:

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

There are however some issues with lambda, so you'd probably better stick to the
first solution.

[snip]
bou_africa=Button(fen1, text='Africa',\
command=rings(size=41, offsetX=0,offsetY=-22,
coul='black'))

(BTW, why do you pass the function arguments as positional parameters in the
first call and as named parameters in the following ones? IMHO, since the
parameters are positional in the function definition, you'd better pass them as
such in the calls, i.e: rings(41, 0, -22, 'black')

(Et sinon, il existe un newsgroup Python francophone (fr.comp.lang.python) sur
lequel tu seras le bienvenu si jamais tu préfères discuter en français)

HTH
 
A

Adam DePrince

I am not only learning Python but programming itself ; reading your
posts makes me believe that nobody is that much of a beginner here. Is
there a newgroup or list for my type somewhere I can't find it ?

To illustrate my case this script :

<CODE>

# function to draw rings for an Olympic flag
def rings(size,offsetX,offsetY,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)

# **main****main****main****main****main****main**

fen1=Tk()
can1=Canvas(fen1, bg='white', height=206, width=340)
can1.pack(side=LEFT)

bou_europe=Button(fen1, text='Europe',\
command=rings(41, 100, -22, 'blue'))
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
973-723-8597 cell voice/tdd
973-983-7576 home voice/tdd
 
A

Adam DePrince

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"
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!

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
Adam DePrince

Adam DePrince
 
L

Lonnie Princehouse

bou_asia=Button(fen1, text='Asia',\
command=rings(size=41, offsetX=50,offsetY=22,
coul='yellow'))

You're calling the rings function when you create the button.

What you really want is for "command" to be a callable object
that the button will invoke when it's clicked, e.g.:

def mycallback():
print 'click'

mybutton = Button(parent, text='a button', command = mycallback)

Notice that there are no parentheses after mycallback -- it's not
being called, but the function itself is being passed as an argument.

In your case, you need to find a way to pass arguments to rings, so
you'll have to curry the function. Here's one way to do it:

def rings_callback(**keywords):
# return an anonymous function that calls rings when invoked.
return lambda k=keywords: rings(**k)

bou_asia = Button(fen1, text='Asia',
command=rings_callback(size=41, offsetX=50,offsetY=22,
coul='yellow'))

Hope that helps.
 
J

Jean Montambeault

Jean said:
I am not only learning Python but programming itself ; reading your
posts makes me believe that nobody is that much of a beginner here. Is
there a newgroup or list for my type somewhere I can't find it ?

To illustrate my case this script :

<CODE>

# function to draw rings for an Olympic flag
def rings(size,offsetX,offsetY,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)

# **main****main****main****main****main****main**

fen1=Tk()
can1=Canvas(fen1, bg='white', height=206, width=340)
can1.pack(side=LEFT)

bou_europe=Button(fen1, text='Europe',\
command=rings(41, 100, -22, 'blue'))
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.

Using Python 2.3, IDLE and Win2k.

Thanks for your time

Jean Montambeault

Thank you everybody !

If Tkinter hadn't been so polite... but without any error message I
didn't know where to start to search. It is a shame that one can't pass
parameters through 'command' in a simple manner. My intent was to make a
function that could be of use in as many cases as possible. I was
experimenting way off the intented target of the exercise. Nevertheless
it was an occasion to learn a whole lot.

Thanks to Simon and Eric the adresses too.

Jean
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top