Turtle true freehand drawing - python

I want to start drawing with the mouse, and I had the idea to do onclick and then the turtle comes to the mouse, and then ondrag turtle I start the freehand drawing, although turtle doesn't detect the dragging. Here is the code. Can you help?
import turtle
def go_to_mouse(x, y):
my_pen.penup()
my_pen.goto(x, y)
my_pen.pendown()
def click_right(x, y):
my_pen.clear()
def drag_handler(x, y):
my_pen.ondrag(None)
my_pen.goto(x, y)
my_pen.ondrag(drag_handler)
window = turtle.Screen()
window.setup(width=1000, height=1000)
window.title('drawing')
window.delay(0)
my_pen = turtle.Turtle()
my_pen.speed(0)
my_pen.color("red")
my_pen.penup()
my_pen.goto(0, 0)
my_pen.pendown()
my_pen.ondrag(drag_handler)
window.onclick(go_to_mouse, 1)
turtle.onscreenclick(click_right, 3)
window.listen()
turtle.mainloop()

Let's first be clear that your code works if you "click again" after the turtle moves to your position. The issue is you don't want to "click again", but rather continue to hold the screen click and start dragging.
The way I was able to figure out to do this was to install and import pyautogui to simulate the missing click:
from turtle import Screen, Turtle
from pyautogui import mouseDown
def go_to_mouse(x, y):
screen.onclick(None, 1) # disable until turtle.release()
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
turtle.onrelease(release_handler)
screen.ontimer(mouseDown)
def click_right(x, y):
turtle.clear()
def drag_handler(x, y):
turtle.ondrag(None)
turtle.goto(x, y)
turtle.ondrag(drag_handler)
def release_handler(x, y):
turtle.onrelease(None)
screen.onclick(go_to_mouse, 1)
screen = Screen()
screen.setup(width=1000, height=1000)
screen.title('drawing')
turtle = Turtle('turtle')
turtle.speed('fastest')
turtle.color('red')
turtle.ondrag(drag_handler)
screen.onclick(go_to_mouse, 1)
screen.onclick(click_right, 3)
screen.mainloop()
I'm using a larger cursor to make sure we don't missposition the "click again". I can't test the right click functionality on my system.

Related

Is there a way to avoid the recursion limit in my Turtle-program?

import turtle
from turtle import Turtle
WIDTH = 1000
HEIGHT = 1000
#Screen setup
screen = turtle.Screen()
screen.setup(WIDTH, HEIGHT)
screen.title(" " *150 + "Test_GIU")
screen.bgcolor("black")
screen.setup(1000, 1000)
#Pen
pen = Turtle("circle")
pen.pensize = 5
pen.color("green")
pen.speed(-1)
def dragging(x, y): # These parameters will be the mouse position
pen.ondrag(None)
pen.setheading(pen.towards(x, y))
pen.goto(x, y)
pen.ondrag(dragging)
def click_on_c():
screen.reset()
pen = Turtle("circle")
pen.pensize = 5
pen.color("green")
pen.speed(-1)
pen.ondrag(dragging)
def main(): # This will run the program
turtle.listen()
pen.ondrag(dragging) # When we drag the turtle object call dragging
turtle.onkeypress(click_on_c, "c")
screen.mainloop() # This will continue running main()
main()
This is my code, im pretty new to it, so its not very good, but its my first real project. I´ve already tried to increase the recursin limit, but it crashes even if I set it to 10000. I also tried to catch the error with an try and exept block, but it also doesnt work.
Let's try a simpler design where instead of calling screen.reset() and recreating the turtle, we instead call pen.reset() to clear the drawing:
from turtle import Screen, Turtle
WIDTH = 1000
HEIGHT = 1000
def dragging(x, y): # Parameters are the mouse position
pen.ondrag(None)
pen.setheading(pen.towards(x, y))
pen.goto(x, y)
pen.ondrag(dragging)
def click_on_c():
pen.reset()
pen.pensize = 5
pen.color("green")
pen.speed('fastest')
# Screen setup
screen = Screen()
screen.setup(WIDTH, HEIGHT)
screen.title("Test_GUI")
screen.bgcolor("black")
# Pen
pen = Turtle("circle")
pen.pensize = 5
pen.color("green")
pen.speed('fastest')
pen.ondrag(dragging)
screen.onkeypress(click_on_c, "c")
screen.listen()
screen.mainloop()
We have to reset some aspects of the pen after calling reset() as that call clears the settings back to the defaults.

How to draw square in Turtle module without filling color?

I am trying to draw a square in turtle without any thing filled in it. I would manually draw it with a loop, but I am trying to write a program where if the square is touched, something would happen. If I drew it with a loop, even if I touch the border, it would not work, because the actual turtle isn't there.
We can do this by dedicating one turtle as the button. We need to change its shape, size and fill color and assign it a button event handler:
from turtle import Screen, Turtle
def thanks(x, y):
marker.write("Thank you!", align='center', font=('Arial', 24, 'bold'))
marker = Turtle()
marker.hideturtle()
marker.penup()
marker.sety(-200)
button = Turtle()
button.shape('square')
button.fillcolor('white')
button.shapesize(3)
button.onclick(thanks)
screen = Screen()
screen.mainloop()
Click on the square in the middle of the screen and it will thank you for doing so.
I am trying to draw a square in turtle without any thing filled in it.
The above solution does use a filled turtle, it just happens to be white fill. We can't draw within the square that is this button. If that's the need, then we can draw the square with a loop, but move our onclick() from the turtle to the screen. We'll need to make the onclick() itself determine if it's in the right place:
from turtle import Screen, Turtle
BUTTON_POSITION = (100, 100)
BUTTON_SIZE = 60
def thanks(x, y):
bx, by = BUTTON_POSITION
if bx < x < bx + BUTTON_SIZE and by < y < by + BUTTON_SIZE:
turtle.write("Thank you!", align='center', font=('Arial', 24, 'bold'))
turtle = Turtle()
turtle.hideturtle()
# draw the button
turtle.penup()
turtle.goto(BUTTON_POSITION)
turtle.pendown()
for _ in range(4):
turtle.forward(BUTTON_SIZE)
turtle.left(90)
# decorate our button a bit
turtle.penup()
turtle.forward(BUTTON_SIZE/2)
turtle.left(90)
turtle.forward(BUTTON_SIZE/2)
turtle.dot()
# position turtle for writing later
turtle.goto(0, -200)
screen = Screen()
screen.onclick(thanks)
screen.mainloop()

how can I change between modes with my button

I created 2 drawing modes but they draw at the same time but i want them to work seperateley so i created a button but dont know how to define the mode change for the button to work
how can I define my mode change so I can change between different drawing modes eg freehandmode, circlemode so they dont work at the same time
from turtle import Screen, Turtle
beni=Screen()
beni.setup(400, 400, 10, 10)
beni.setworldcoordinates(-300, -300, 300, 300)
def mode_change(x, y):
#freehandmode
def freehandmode(x, y):
t.ondrag(None)
t.setheading(t.towards(x, y))
t.goto(x, y)
t.ondrag(freehandmode)
#circlemode
def draw_circle(x, y):
beni.onclick(None)
center = turtle.position()
turtle.setposition(x, y)
turtle.setheading(turtle.towards(center) - 90)
turtle.pendown()
turtle.circle(turtle.distance(center))
turtle.penup()
turtle.clearstamps()
beni.onclick(pick_center)
def pick_center(x, y):
beni.onclick(None)
turtle.setposition(x, y)
turtle.stamp()
beni.onclick(draw_circle)
turtle = Turtle()
turtle.hideturtle()
turtle.shape('circle')
turtle.shapesize(0.5)
turtle.penup()
beni.onclick(pick_center)
#freehand turtle
t = Turtle('circle')
t.shapesize(1)
t.speed('fastest')
t.ondrag(freehandmode)
#modechange turtle
modechange = Turtle('circle')
modechange.pu()
modechange.shapesize(0.55, 1.45)
modechange.color('black')
modechange.setpos(0, 290)
modechange.onclick(mode_change)
#modebutton
modebutton = Turtle()
modebutton.shapesize(0.25)
modebutton.pu()
modebutton.setpos(-20, 300)
modebutton.setheading(270)
modebutton.pd()
modebutton.fd(20)
modebutton.setheading(0)
modebutton.fd(45)
modebutton.setheading(90)
modebutton.fd(20)
modebutton.setheading(180)
modebutton.fd(45)
modebutton.pu()
modebutton.setpos(-10, 263)
modebutton.setheading(0)
modebutton.color('green')
modebutton.write('Modi')
modebutton.hideturtle()
beni.mainloop()
It's mostly a matter of accounting -- you need to explicitly list steps necessary to disable one turtle and enable the other every time you switch modes. And you need to keep track of the current mode. Here's my rework and simplification of your (actually, largely my) code to do this:
from turtle import Screen, Turtle, mainloop
def mode_change(x, y):
global mode
if mode == 'freehand':
# disable freehand
freehand.ondrag(None)
freehand.hideturtle()
# enable circle
screen.ontimer(lambda: screen.onclick(pick_center)) # so screen doesn't inherit *this* click
mode = 'circle'
else:
# disable circle
screen.onclick(None)
# enable freehand
freehand.ondrag(freehandmode)
freehand.showturtle()
mode = 'freehand'
# freehand mode
def freehandmode(x, y):
freehand.ondrag(None)
freehand.setheading(freehand.towards(x, y))
freehand.goto(x, y)
freehand.ondrag(freehandmode)
# circle mode
def draw_circle(x, y):
screen.onclick(None)
center = circle.position()
circle.setposition(x, y)
circle.setheading(circle.towards(center) - 90)
circle.pendown()
circle.circle(circle.distance(center))
circle.penup()
circle.clearstamps()
screen.onclick(pick_center)
def pick_center(x, y):
screen.onclick(None)
circle.setposition(x, y)
circle.stamp()
screen.onclick(draw_circle)
screen = Screen()
screen.setup(400, 400)
mode = 'freehand'
circle = Turtle('circle', visible=False)
circle.shapesize(0.5)
circle.speed('fastest')
circle.penup()
freehand = Turtle('circle')
freehand.speed('fastest')
freehand.ondrag(freehandmode)
# modechange turtle
modechange = Turtle('square')
modechange.penup()
modechange.setposition(0, 155)
modechange.pencolor('green')
modechange.write('Modi', align='center')
modechange.shapesize(2.25, 1.0)
modechange.setposition(0, 190)
modechange.onclick(mode_change)
mainloop()

How can I make my turtle move to my cursor?

I am trying to move the turtle to my cursor to draw something so that every time I click, the turtle will go there and draw something.
I have already tried onscreenclick(), onclick, and many combinations of both, I feel like I am doing something wrong, but I don't know what.
from turtle import*
import random
turtle = Turtle()
turtle.speed(0)
col = ["red","green","blue","orange","purple","pink","yellow"]
a = random.randint(0,4)
siz = random.randint(100,300)
def draw():
for i in range(75):
turtle.color(col[a])
turtle.forward(siz)
turtle.left(175)
TurtleScreen.onclick(turtle.goto)
Any help would be great, thank you for your time ( If you help me! ;)
It's not so much what method you're invoking, but on what object you're invoking it:
TurtleScreen.onclick(turtle.goto)
TurtleScreen is a class, you need to call it on a screen instance. And since you want to call draw in addition to turtle.goto you need to define your own function that calls both:
screen = Screen()
screen.onclick(my_event_handler)
Here's a rework of your code with the above fixes and other tweaks:
from turtle import Screen, Turtle, mainloop
from random import choice, randint
COLORS = ["red", "green", "blue", "orange", "purple", "pink", "yellow"]
def draw():
size = randint(100, 300)
# make turtle position center of drawing
turtle.setheading(0)
turtle.setx(turtle.xcor() - size/2)
turtle.pendown()
for _ in range(75):
turtle.color(choice(COLORS))
turtle.forward(size)
turtle.left(175)
turtle.penup()
def event_handler(x, y):
screen.onclick(None) # disable event handler inside event handler
turtle.goto(x, y)
draw()
screen.onclick(event_handler)
turtle = Turtle()
turtle.speed('fastest')
turtle.penup()
screen = Screen()
screen.onclick(event_handler)
mainloop()

Creating a turtle program that does commands based upon the button pressed

I haven't been able to find anything online for this but I need to create a program that:
If the left button is pressed, the turtle should move to that location and draw a small square.
If the right button is pressed, the turtle should move that that location and draw a small circle.
If the middle button is pressed, the turtle should change to a different random color.
You should also change the color if the use presses the space bar.
Any suggestions on how to start?
Here is some code I have tried so far:
def k2(x,y): turtle.penup() turtle.setposition(x,y) turtle.pendown() turtle.circle(radius)
This is the top from turtle
import * setup(500, 500) Screen() title("Turtle Keys") move = Turtle() showturtle()
This is the bottom
onkey(k1, "Up") onkey(k2, "Left") onkey(k3, "Right") onkey(k4, "Down") listen() mainloop()
Below is my guess as to what you and your code snippets describe. Note that I changed the circle and square functions from the left and right keyboard buttons to the left and right mouse buttons which seemed to make more sense in the context of, "move to that location":
import turtle
import random
colors = ["red", "orange", "yellow", "green", "blue", "violet"]
radius = 10
width = 20
LEFT, MIDDLE, RIGHT = 1, 2, 3
def k1(x=None, y=None): # dummy arguments so can be a click or key
turtle.color(random.choice(colors))
def k2(x, y):
turtle.penup()
turtle.setposition(x, y)
turtle.pendown()
for _ in range(4):
turtle.forward(width)
turtle.right(90)
def k3(x, y):
turtle.penup()
turtle.setposition(x, y)
turtle.pendown()
turtle.circle(radius)
turtle.setup(500, 500)
turtle.Screen().title("Turtle Keys")
turtle.onkey(k1, " ")
turtle.onscreenclick(k2, btn=LEFT)
turtle.onscreenclick(k1, btn=MIDDLE)
turtle.onscreenclick(k3, btn=RIGHT)
turtle.listen()
turtle.mainloop()

Categories