Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Detecting a click on the turtle screen when the turtle isn't doinganything? (http://www.velocityreviews.com/forums/t957295-detecting-a-click-on-the-turtle-screen-when-the-turtle-isnt-doinganything.html)

Adam Funk 02-05-2013 01:20 PM

Detecting a click on the turtle screen when the turtle isn't doinganything?
 
I'm trying to get a program to do some plotting with turtle graphics,
then wait for the user to click on the graphics window, then do some
more plotting, &c. So far I have the following, which doesn't work:

#v+
waiting = False

def clicked(x, y):
global waiting
print('clicked at %f %f' % (x,y))
waiting = False
return

def wait_for_click(s):
global waiting
waiting = True
s.listen()
while waiting:
time.sleep(1)
return


....
t = turtle.Pen()
s = turtle.Screen()
....
traverse.plot(s, t, "black", scale, adjx, adjy)
wait_for_click(s)
bowditch.plot(s, t, "red", scale, adjx, adjy)
wait_for_click(s)
transit.plot(s, t, "blue", scale, adjx, adjy)
wait_for_click(s)
#v-


Each of my plot(..) calls does some turtle movement, and I want the
program to sit and wait for the user to click the graphics window,
then add the next plot. I've played around with some event handling
examples I found [1], and concluded that the onclick binding only
works while the turtle is doing something. Is that correct? Is there
a way to wait for the click & hear it while the turtle is not doing
anything?


[1] <http://csil-web.cs.surrey.sfu.ca/cmpt120fall2010/wiki/IntroToEventHandling/>


Thanks,
Adam


--
But the government always tries to coax well-known writers into the
Establishment; it makes them feel educated. [Robert Graves]

woooee@gmail.com 02-05-2013 06:08 PM

Re: Detecting a click on the turtle screen when the turtle isn'tdoing anything?
 
> waiting = False
>
>
>
> def clicked(x, y):
>
> global waiting
>
> print('clicked at %f %f' % (x,y))
>
> waiting = False
>
> return
>
>
>
> def wait_for_click(s):
>
> global waiting
>
> waiting = True
>
> s.listen()
>
> while waiting:
>
> time.sleep(1)
>
> return
>
>
>
>
>
> ...
>
> t = turtle.Pen()
>
> s = turtle.Screen()
>
> ...
>
> traverse.plot(s, t, "black", scale, adjx, adjy)
>
> wait_for_click(s)
>
> bowditch.plot(s, t, "red", scale, adjx, adjy)
>
> wait_for_click(s)
>
> transit.plot(s, t, "blue", scale, adjx, adjy)
>
> wait_for_click(s)


Note that the code you posted does not call onclick(). Globals are confusing IMHO. Code becomes cleaner and easier to write and read when you become familiar with classes.

import turtle

class TurtleTest():
def __init__(self):
self.ctr=0

t = turtle.Turtle()
s = turtle.Screen()
s.onclick(self.clicked)
turtle.mainloop()

def clicked(self, x, y):
print self.ctr
if 0 == self.ctr:
self.first()
elif 1 == self.ctr:
self.second()
elif 2 == self.ctr:
self.third()

self.ctr += 1

def first(self):
print "first called"

def second(self):
print "second called"

def third(self):
print "third called"

TT = TurtleTest()

Adam Funk 02-05-2013 07:45 PM

Re: Detecting a click on the turtle screen when the turtle isn'tdoing anything?
 
On 2013-02-05, Adam Funk wrote:

> I'm trying to get a program to do some plotting with turtle graphics,
> then wait for the user to click on the graphics window, then do some
> more plotting, &c. So far I have the following, which doesn't work:
>
> #v+
> waiting = False
>
> def clicked(x, y):
> global waiting
> print('clicked at %f %f' % (x,y))
> waiting = False
> return
>
> def wait_for_click(s):
> global waiting
> waiting = True
> s.listen()
> while waiting:
> time.sleep(1)
> return
>
>
> ...
> t = turtle.Pen()
> s = turtle.Screen()


Oops, I snipped out two important lines:

#v+
s.onclick(clicked, btn=1)
wait_for_click(s, t)
#v-

> ...
> traverse.plot(s, t, "black", scale, adjx, adjy)
> wait_for_click(s)
> bowditch.plot(s, t, "red", scale, adjx, adjy)
> wait_for_click(s)
> transit.plot(s, t, "blue", scale, adjx, adjy)
> wait_for_click(s)
> #v-
>
>
> Each of my plot(..) calls does some turtle movement, and I want the
> program to sit and wait for the user to click the graphics window,
> then add the next plot. I've played around with some event handling
> examples I found [1], and concluded that the onclick binding only
> works while the turtle is doing something. Is that correct? Is there
> a way to wait for the click & hear it while the turtle is not doing
> anything?
>
>
> [1] <http://csil-web.cs.surrey.sfu.ca/cmpt120fall2010/wiki/IntroToEventHandling/>
>
>
> Thanks,
> Adam
>
>



--
Master Foo said: "A man who mistakes secrets for knowledge is like
a man who, seeking light, hugs a candle so closely that he smothers
it and burns his hand." --- Eric Raymond

Adam Funk 02-05-2013 07:58 PM

Re: Detecting a click on the turtle screen when the turtle isn'tdoing anything?
 
On 2013-02-05, woooee@gmail.com wrote:

> Note that the code you posted does not call onclick().


It does, actually, but I accidentally snipped it when C&Ping code into
my original post. Sorry!

> Globals are
> confusing IMHO. Code becomes cleaner and easier to write and read
> when you become familiar with classes.


I've already got a module with Course and Traverse classes (this is
for surveying problems). If I have to write a class just to create
one instance of it & call the main() method, I might as well use Java!
;-)

But I'll work through the example you posted --- thanks.


--
Master Foo said: "A man who mistakes secrets for knowledge is like
a man who, seeking light, hugs a candle so closely that he smothers
it and burns his hand." --- Eric Raymond

Dennis Lee Bieber 02-05-2013 09:54 PM

Re: Detecting a click on the turtle screen when the turtle isn'tdoing anything?
 
On Tue, 05 Feb 2013 19:45:18 +0000, Adam Funk <a24061@ducksburg.com>
declaimed the following in gmane.comp.python.general:

> >
> > #v+
> > waiting = False
> >
> > def clicked(x, y):
> > global waiting
> > print('clicked at %f %f' % (x,y))
> > waiting = False
> > return
> >
> > def wait_for_click(s):
> > global waiting
> > waiting = True
> > s.listen()
> > while waiting:
> > time.sleep(1)
> > return
> >


I'll echo the "Ugh" about the use of global AND ADD a dislike of the
busy loop that only exits if some other return sets a value. If the busy
loop were performing some action that changed the test state within the
loop itself, okay...

-=-=-=-
import threading

evtFlag = threading.Event()

def clicked(x, y):
print("clicked at %f %f" % (x, y))
evtFlag.set()
#don't need "global" as not binding to the name evtFlag
#don't need "return" as falling off the end of the function
# implements return

def wait_for_clicks(s):
evtFlag.clear()
s.listen()
evtFlag.wait()
#don't need "global" or "return"
#don't need busy loop; .wait() blocks until some other thread
# (GUI callback) sets the Event

--
Wulfraed Dennis Lee Bieber AF6VN
wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/


Dave Angel 02-05-2013 09:55 PM

Re: Detecting a click on the turtle screen when the turtle isn'tdoing anything?
 
On 02/05/2013 02:58 PM, Adam Funk wrote:
> On 2013-02-05, woooee@gmail.com wrote:
>
>> <SNIP>

>
>> Globals are
>> confusing IMHO. Code becomes cleaner and easier to write and read
>> when you become familiar with classes.

>

<snip>
> If I have to write a class just to create
> one instance of it & call the main() method, I might as well use Java!
> ;-)
>


I'm no fan of Java. But it's not about a "main" method, it's about
sharing data between functions. Most of the time non-constant globals
are a mistake. If the data can't be passed as an argument, then it
should probably be part of the instance data of some class. Which class
is a design decision, and unlike Java, I wouldn't encourage writing a
class for unrelated functions, just to bundle them together.


Anyway, back to your problem. Since your code doesn't have threads, it
must have an event loop somewhere. Event loops don't coexist at all
well with calls to sleep().

while waiting:
time.sleep(1)

If you start that code with waiting being true, it will never terminate.

I don't know turtle graphics, but if it's got an event loop, then you
can't write your program procedurally. A function called
"wait_for_click()" is nonsensical.


--
DaveA

Adam Funk 02-06-2013 09:46 PM

Re: Detecting a click on the turtle screen when the turtle isn'tdoing anything?
 
On 2013-02-05, Dave Angel wrote:

> I'm no fan of Java. But it's not about a "main" method, it's about
> sharing data between functions. Most of the time non-constant globals
> are a mistake. If the data can't be passed as an argument, then it
> should probably be part of the instance data of some class. Which class
> is a design decision, and unlike Java, I wouldn't encourage writing a
> class for unrelated functions, just to bundle them together.


Well, I understand the OO principle there, but it seems practical to
accept a few global variables in the "main" code of a program.
Anyway...


> Anyway, back to your problem. Since your code doesn't have threads, it
> must have an event loop somewhere. Event loops don't coexist at all
> well with calls to sleep().
>
> while waiting:
> time.sleep(1)
>
> If you start that code with waiting being true, it will never terminate.


Right. But the following *does* work (although it's probably
offensive):

#v+
def wait_for_click(s, t):
global waiting
waiting = True
s.listen()
t.hideturtle()
t.penup()
while waiting:
t.forward(5)
t.right(5)
return
#v-



--
A lot of people never use their intiative because no-one
told them to. --- Banksy

Adam Funk 02-06-2013 09:52 PM

Re: Detecting a click on the turtle screen when the turtle isn'tdoing anything?
 
On 2013-02-05, Dennis Lee Bieber wrote:

> I'll echo the "Ugh" about the use of global AND ADD a dislike of the
> busy loop that only exits if some other return sets a value. If the busy
> loop were performing some action that changed the test state within the
> loop itself, okay...


TBH, I was originally going to use

input('press RETURN to continue')

but I thought it would be nicer to click on the plot window.


> -=-=-=-
> import threading
>
> evtFlag = threading.Event()


This is a global variable, but here we're calling a method on it
rather than changing its value (boolean in my original case). Why is
that better in principle?


> def clicked(x, y):
> print("clicked at %f %f" % (x, y))
> evtFlag.set()
> #don't need "global" as not binding to the name evtFlag
> #don't need "return" as falling off the end of the function
> # implements return


Does it do any harm to put an empty "return" at the end of a method?
(It looks tidier to me with the return.)


> def wait_for_clicks(s):
> evtFlag.clear()
> s.listen()
> evtFlag.wait()
> #don't need "global" or "return"
> #don't need busy loop; .wait() blocks until some other thread
> # (GUI callback) sets the Event


I tried these and got even worse results --- even Ctrl-C in the xterm
I was running the program from wouldn't kill it; I had to use Ctrl-Z
and kill %1.


--
It would be unfair to detect an element of logic in the siting of the
Pentagon alongside the National Cemetery, but the subject seems at
least worthy of investigation. --- C Northcote Parkinson


All times are GMT. The time now is 01:14 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.