Bind Python turtle exitonclick() function to another key - python

I am using Python 2.7 turtle graphics to make a simple mouse sensor that draws whenever you hold down the mouse button. Since my function is based on the user, it crashes right when you run it. I found out that turtle.exitonclick() will help keep the interface on, but I can't draw because my draw is bound to the left mouse button click. Is there any solution to get around this or is it possible to rebind turtle.exitonclick() to something else? Here's my code:
import turtle
wn = turtle.Screen()
wn.bgcolor("lightblue")
#wn.screensize(400,300)
turtle.setup(400,300)
draw = turtle.Turtle()
def gothere(event):
draw.penup()
draw.goto(event.x-360, 340-event.y)
draw.pendown()
#draw.color(blue)
def movearound(event):
draw.goto(event.x-360, 340-event.y)
draw.color(blue)
def release(event):
draw.penup()
def reset(event):
draw.clear()
cavset = turtle.getcanvas()
cavset.bind("<Button-2>", gothere)
cavset.bind("<B1-Motion>", movearound)
cavset.bind("<ButtonRelease-2>", release)
cavset.bind("<Escape>", reset)
wn.listen()
wn.exitonclick()
(I am running through command prompt, BTW.)

What you most likely want is:
turtle.mainloop()
instead of:
wn.exitonclick()
as that's what exitonclick() calls after setting up a handler for the "onclick" part.
However, there are other issues. You seem to be mixing three different coding models: functional interface to turtle; object-oriented interface to turtle; calling into turtle's Tkinter underpinnings.
Let's simplify and just use the object-oriented interface to turtle:
from turtle import Turtle, Screen, mainloop
def gothere(x, y):
draw.penup()
draw.goto(x, y)
draw.pendown()
def movearound(x, y):
draw.ondrag(None) # disable handler in handler!
draw.color("blue")
draw.goto(x, y)
draw.ondrag(movearound)
def release(x, y):
draw.penup()
def reset():
draw.clear()
wn = Screen()
wn.setup(400, 300)
wn.bgcolor("lightblue")
draw = Turtle()
wn.onclick(gothere, 2)
draw.ondrag(movearound)
draw.onrelease(release, 2)
wn.onkey(reset, "Escape")
wn.listen()
mainloop()
I believe Python 3 turtle tweaks the turtle event interface to add some methods and use clearer names for others.

Related

Up arrow key not working for python turtle

I have used the onkey function for the right and left:
sc.onkey(user_left,"left")
sc.onkey(user_right,"right")
I have also set the screen after setting the turtle and importing turtle:
sc=Screen()
But when I use the same format for up and down:
sc.onkey(user_up,"up")
sc.onkey(user_down,"down")
It does nothing. I also have my functions:
def user_right:
t3.forward(5)
def user_left:
t3.backward(5)
t3 is my user turtle, and it is sideways, the shape is turtle, and its head is facing right. t3 is automatically set to make its head facing the right side when the code runs. By the way, I import from turtle import*
I see several issues here. First, this can't work as you claim:
def user_right:
t3.forward(5)
def user_left:
t3.backward(5)
It would need to be:
def user_right():
t3.forward(5)
def user_left():
t3.backward(5)
Next, this won't work in turtle in standard Python:
sc.onkey(user_left,"left")
sc.onkey(user_right,"right")
These keys would have to be "Left" and "Right". Are you using a non-standard turtle implementation? (E.g. the one on repl.it) You show your two event handlers that work, but fail to show the two that don't which would be of more interest when trying to debug your code.
Finally, your missing a call to the screen's listen() method, so your keystrokes are ignored. Here's how I might implement the functionality your code is hinting at:
from turtle import Screen, Turtle
def user_right():
turtle.forward(5)
def user_left():
turtle.backward(5)
def user_up():
turtle.sety(turtle.ycor() + 5)
def user_down():
turtle.sety(turtle.ycor() - 5)
turtle = Turtle()
turtle.shape('turtle')
screen = Screen()
screen.onkey(user_left, 'Left')
screen.onkey(user_right, 'Right')
screen.onkey(user_up, 'Up')
screen.onkey(user_down, 'Down')
screen.listen()
screen.mainloop()

Python 3 Turtle Graphics: Mouse coordinates [duplicate]

I'm assigned to create a similar version of slither.io in python. I planned on using Turtle. How do I make the turtle follow my mouse without having to click every time?
This is how I would do it when clicking, but I would rather not have to click:
from turtle import *
turtle = Turtle()
screen = Screen()
screen.onscreenclick(turtle.goto)
turtle.getscreen()._root.mainloop()
The key to it is to use the ondrag() event handler on a turtle. A short and not so sweet solution:
import turtle
turtle.ondrag(turtle.goto)
turtle.mainloop()
which will likely crash shortly after you start dragging. A better solution with a larger turtle to drag, and that turns off the drag handler inside the drag hander to prevent events from piling up:
from turtle import Turtle, Screen
def dragging(x, y):
yertle.ondrag(None)
yertle.setheading(yertle.towards(x, y))
yertle.goto(x, y)
yertle.ondrag(dragging)
screen = Screen()
yertle = Turtle('turtle')
yertle.speed('fastest')
yertle.ondrag(dragging)
screen.mainloop()
Note that you have to click and drag the turtle itself, not just click somewhere on the screen. If you want to get the turtle to follow the mouse without keeping the left button held down, see my answer to Move python turtle with mouse pointer.

Python 3 turtle speed of drawing

I am creating a game in python using turtle but I am unable to control the speed of the turtle in the loop as the speed of the turtle is 0. It is supposed to run like flash but it is running at normal speed
import turtle
c=turtle.Screen()
a=turtle.Turtle()
a.speed(0)
b=True
def ch( a , d):
global b
b = False
while b:
a.fd(1)
c.onclick(ch)
c.mainloop()
speed(0) can only speed up the animations a bit.
Try using c.tracer(0, 0)
This fully disables all animations, and should result it a bit more of a speed up. Although, to refresh the screen you'll need to call c.update()
First, your code is structured incorrectly. You don't need to call onclick() in a loop, it simply sets a handler function so only needs to be called once. Also, mainloop() should be running the events, not called after the events are over.
I don't believe you're going get any more speed out of this code unless you increase the forward distance. Simply increading to fd(3) will make a noticeable differece. My rework of your code:
from turtle import Turtle, Screen
def click_handler(x, y):
global flag
flag = False
def turtle_forward():
if flag:
turtle.forward(3)
screen.ontimer(turtle_forward, 0)
flag = True
screen = Screen()
screen.onclick(click_handler)
turtle = Turtle()
turtle.speed('fastest')
turtle_forward()
screen.mainloop()

Python, Turtle Graphics, Key bindings

I'm trying to figure out a way to make it to when I hold down a key the player will constantly move, or just have the player move forward constantly with just turtle graphics, (I do have pygame installed also)
import turtle
from turtle import *
#Setup Screen
wn = turtle.Screen()
wn.setup(700,700)
wn.title("white")
wn.bgcolor("black")
#Create Player
player = turtle.Turtle()
player.penup()
player.shape("triangle")
player.color("white")
def forward():
player.forward(20)
def lef():
player.left(90)
def forward():
player.right(90)
onkey(forward,"Up")
onkey(left,"Left")
onkey(right,"Right")
listen()
You can fix it simply by adding wn to start of
wn.onkey(forward, 'Up')
wn.onkey(left, 'Left')
wn.onkey(right, 'Right')
wn.listen()
wn.mainloop()
I hope this helps!
I recommend you read this post on repeating key events and first determine whether your operating system provides key repeat and whether you can/want to adjust that and/or how to turn it off to implement your own. That link includes code to implement your own key repeat behavior in turtle.
I've reworked your code below and the keys repeat fine for me because my operating system (OSX) implements key repeat:
from turtle import Turtle, Screen
# Setup Screen
wn = Screen()
wn.setup(700, 700)
wn.title('white')
wn.bgcolor('black')
# Create Player
player = Turtle('triangle')
player.speed('fastest')
player.color('white')
player.penup()
def forward():
player.forward(20)
def left():
player.left(90)
def right():
player.right(90)
wn.onkey(forward, 'Up')
wn.onkey(left, 'Left')
wn.onkey(right, 'Right')
wn.listen()
wn.mainloop()
In OSX I can control the rate (and turn it off) in the Keyboard panel of Systems Preferences. Look into what your OS provides.
Some programming notes: avoid importing the same module two different ways, this always leads to confusion. If you find you're getting interference between keyboard events at high repetition rates consider the following for all three event handlers:
def forward():
wn.onkey(None, 'Up') # disable event in handler
player.forward(20)
wn.onkey(forward, 'Up') # reenable event
If you are using python 3 then you should use wn.onkeypress(). The function onkey() is triggered when the key is pressed and then released but the onkeypress() function is triggered immediately when a key is pressed down.

Python turtle.ondrag not working

I've been trying to make a paint program in Python Turtle and for some reason it won't work. I'm using the pen() tool and my code looks like this
from turtle import *
import random
pen()
bgcolor('black')
pencolor('white')
pen.ondrag(pen.goto)
listen()
mainloop()
I've look at this http://docs.python.org/2/library/turtle.html and it says to type turtle.ondrag(turtle.goto) but since I'm using the pen it should work as pen.ondrag but it doesn't, so can someone please clear this up.
Thanks Jellominer
I will simplify and clarify the code given by the questionner:
from turtle import *
ts = Screen(); tu = Turtle()
ts.listen()
ondrag(tu.goto)
mainloop()
This works. You have to click on the turtle and drag it.
First, pen() is not the function you want. Second, although Pen is a synonym for Turtle, pen is not a synonym for turtle. Here's how to go about using ondrag() if you'd like to use Pen instead of Turtle:
from turtle import Pen, Screen, mainloop
def ondrag_handler(x, y):
pen.ondrag(None) # disable handler inside handler
pen.setheading(pen.towards(x, y)) # turn toward cursor
pen.goto(x, y) # move toward cursor
pen.ondrag(ondrag_handler)
screen = Screen()
screen.bgcolor('black')
pen = Pen()
pen.color('white')
pen.shapesize(2) # make it larger so it's easier to drag
pen.ondrag(ondrag_handler)
screen.listen()
mainloop() # screen.mainloop() preferred but not in Python 2
The turtle.ondrag(turtle.goto) makes for a nice short example in the documentation but in reality isn't practical. You want to disable the event handler while handling the event otherwise the events stack up against you. And it's nice to turn the mouse towards your cursor as you drag it.
from turtle import *
ts = Screen()
ondrag(goto)
shapesize(10)
pensize(40)
speed(0)
mainloop()
I think this will surely work.
You can change the size and other things
In here you are using the default turtle .
Sorry but you'll need to take care of the indentation

Categories