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

Discussion in 'Python' started by Adam Funk, Feb 5, 2013.

  1. Adam Funk

    Adam Funk Guest

    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]
    Adam Funk, Feb 5, 2013
    #1
    1. Advertising

  2. Adam Funk

    Guest

    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()
    , Feb 5, 2013
    #2
    1. Advertising

  3. Adam Funk

    Adam Funk Guest

    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, Feb 5, 2013
    #3
  4. Adam Funk

    Adam Funk Guest

    Re: Detecting a click on the turtle screen when the turtle isn'tdoing anything?

    On 2013-02-05, 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
    Adam Funk, Feb 5, 2013
    #4
  5. 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 <>
    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
    HTTP://wlfraed.home.netcom.com/
    Dennis Lee Bieber, Feb 5, 2013
    #5
  6. Adam Funk

    Dave Angel Guest

    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, 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
    Dave Angel, Feb 5, 2013
    #6
  7. Adam Funk

    Adam Funk Guest

    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, Feb 6, 2013
    #7
  8. Adam Funk

    Adam Funk Guest

    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
    Adam Funk, Feb 6, 2013
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Erik  Bethke
    Replies:
    0
    Views:
    606
    Erik Bethke
    Feb 21, 2005
  2. Replies:
    8
    Views:
    4,204
    Andrew Thompson
    Aug 13, 2006
  3. Chris Wilkins

    Detecting keypress when window isn't in focus

    Chris Wilkins, Jul 25, 2008, in forum: Perl Misc
    Replies:
    2
    Views:
    170
    J├╝rgen Exner
    Jul 25, 2008
  4. laredotornado

    Why isn't invoking "click" doing what I want?

    laredotornado, Jan 16, 2009, in forum: Javascript
    Replies:
    1
    Views:
    66
    Erwin Moller
    Jan 16, 2009
  5. Replies:
    0
    Views:
    79
Loading...

Share This Page