Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #38191 > unrolled thread

Detecting a click on the turtle screen when the turtle isn't doing anything?

Started byAdam Funk <a24061@ducksburg.com>
First post2013-02-05 13:20 +0000
Last post2013-02-06 21:52 +0000
Articles 8 — 4 participants

Back to article view | Back to comp.lang.python


Contents

  Detecting a click on the turtle screen when the turtle isn't doing anything? Adam Funk <a24061@ducksburg.com> - 2013-02-05 13:20 +0000
    Re: Detecting a click on the turtle screen when the turtle isn't doing anything? woooee@gmail.com - 2013-02-05 10:08 -0800
      Re: Detecting a click on the turtle screen when the turtle isn't doing anything? Adam Funk <a24061@ducksburg.com> - 2013-02-05 19:58 +0000
        Re: Detecting a click on the turtle screen when the turtle isn't doing anything? Dave Angel <d@davea.name> - 2013-02-05 16:55 -0500
          Re: Detecting a click on the turtle screen when the turtle isn't doing anything? Adam Funk <a24061@ducksburg.com> - 2013-02-06 21:46 +0000
    Re: Detecting a click on the turtle screen when the turtle isn't doing anything? Adam Funk <a24061@ducksburg.com> - 2013-02-05 19:45 +0000
      Re: Detecting a click on the turtle screen when the turtle isn't doing anything? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-02-05 16:54 -0500
        Re: Detecting a click on the turtle screen when the turtle isn't doing anything? Adam Funk <a24061@ducksburg.com> - 2013-02-06 21:52 +0000

#38191 — Detecting a click on the turtle screen when the turtle isn't doing anything?

FromAdam Funk <a24061@ducksburg.com>
Date2013-02-05 13:20 +0000
SubjectDetecting a click on the turtle screen when the turtle isn't doing anything?
Message-ID<5id7u9x7rd.ln2@news.ducksburg.com>
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]

[toc] | [next] | [standalone]


#38209

Fromwoooee@gmail.com
Date2013-02-05 10:08 -0800
Message-ID<8e3f3198-3657-4abc-b367-06479a561e41@googlegroups.com>
In reply to#38191
> 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()

[toc] | [prev] | [next] | [standalone]


#38223

FromAdam Funk <a24061@ducksburg.com>
Date2013-02-05 19:58 +0000
Message-ID<6s48u9x49o.ln2@news.ducksburg.com>
In reply to#38209
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

[toc] | [prev] | [next] | [standalone]


#38235

FromDave Angel <d@davea.name>
Date2013-02-05 16:55 -0500
Message-ID<mailman.1391.1360101376.2939.python-list@python.org>
In reply to#38223
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

[toc] | [prev] | [next] | [standalone]


#38305

FromAdam Funk <a24061@ducksburg.com>
Date2013-02-06 21:46 +0000
Message-ID<9ivau9xovn.ln2@news.ducksburg.com>
In reply to#38235
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

[toc] | [prev] | [next] | [standalone]


#38224

FromAdam Funk <a24061@ducksburg.com>
Date2013-02-05 19:45 +0000
Message-ID<e348u9x18o.ln2@news.ducksburg.com>
In reply to#38191
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

[toc] | [prev] | [next] | [standalone]


#38233

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2013-02-05 16:54 -0500
Message-ID<mailman.1389.1360101284.2939.python-list@python.org>
In reply to#38224
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/

[toc] | [prev] | [next] | [standalone]


#38306

FromAdam Funk <a24061@ducksburg.com>
Date2013-02-06 21:52 +0000
Message-ID<0tvau9x01o.ln2@news.ducksburg.com>
In reply to#38233
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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web