Trigger event when text is clicked in Python Turtle - python

I'm currently making a program in python's Turtle Graphics. Here is my code in case you need it
import turtle
turtle.ht()
width = 800
height = 800
turtle.screensize(width, height)
##Definitions
def text(text, size, color, pos1, pos2):
turtle.penup()
turtle.goto(pos1, pos2)
turtle.color(color)
turtle.begin_fill()
turtle.write(text, font=('Arial', size, 'normal'))
turtle.end_fill()
##Screen
turtle.bgcolor('purple')
text('This is an example', 20, 'orange', 100, 100)
turtle.done()
I want to have click events. So, where the text 'This is an example' is wrote, I want to be able to click that and it prints something to the console or changes the background. How do I do this?
I don't want to install anything like pygame, it has to be made in Turtle

Use the onscreenclick method to get the position then act on it in your mainloop (to print or whatever).
import turtle as t
def main():
t.onscreenclick(getPos)
t.mainloop()
main()
Also see : Python 3.0 using turtle.onclick
Also see : Turtle in python- Trying to get the turtle to move to the mouse click position and print its coordinates

Since your requirement is to have onscreenclick around text area, we need
to track mouse position. For that we are binding function onTextClick to the screenevent.
Within function, if we are anywere around text This is an example , a call is made to turtle.onscreenclick to change color of the background to red.
You can change lambda function and insert your own, or just create external function and call within turtle.onscreenclick as per this documentation
I tried to change your code as little as possible.
Here is a working Code:
import turtle
turtle.ht()
width = 800
height = 800
turtle.screensize(width, height)
##Definitions
def text(text, size, color, pos1, pos2):
turtle.penup()
turtle.goto(pos1, pos2)
turtle.color(color)
turtle.begin_fill()
turtle.write(text, font=('Arial', size, 'normal'))
turtle.end_fill()
def onTextClick(event):
x, y = event.x, event.y
print('x={}, y={}'.format(x, y))
if (x >= 600 and x <= 800) and ( y >= 280 and y <= 300):
turtle.onscreenclick(lambda x, y: turtle.bgcolor('red'))
##Screen
turtle.bgcolor('purple')
text('This is an example', 20, 'orange', 100, 100)
canvas = turtle.getcanvas()
canvas.bind('<Motion>', onTextClick)
turtle.done()

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()

Turtle true freehand drawing

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.

Turtle colour doesn't change with variable and list

So this is my code right now and the problem should be somwehere between Line 18 and 37. What I want to do is that when the user clicks on the top left turtle, it changes to the next colour. The turtle in the top left is only optical and has no other function than telling the user where to click (at least that's the idea). The problem is that it doesn't do that and I don't really get why
import turtle
from turtle import *
# def on_click_handler(x,y):
# print("Clicked: " , [x,y])
# t1.goto(x,y)
sc = Screen()
sc.setup(400, 400, 10, 10)
sc.setworldcoordinates(-300, -300, 300, 300)
# sc.onscreenclick(on_click_handler)
t1 = Turtle("turtle")
t1.shape("circle")
t1.shapesize(0.25, 0.25)
t1.speed(-1)
#changing turtle colour
tcolour = Turtle("turtle")
tcolour.penup()
tcolour.shape("square")
tcolour.shapesize(1, 1.5)
tcolour.setpos(-275, 285)
colour_list = ["#000000", "#0101DF", "#04B404", "#FF0000", "#FF8000", "B40486"] #black, blue, green, red, orange, purple
n = 0
def colourchange(x, y):
if (x < -275 and x > -300 and y > 284 and y < 300):
global n
n += 1
turtle.onscreenclick(colourchange, 1)
turtle.listen()
t1.color(colour_list[0+n])
def dragging(x, y):
t1.ondrag(None)
t1.setheading(t1.towards(x, y))
t1.goto(x, y)
t1.ondrag(dragging)
def clickright(x, y):
t1.clear()
def main():
turtle.listen()
t1.ondrag(dragging)
turtle.onscreenclick(clickright, 3)
sc.mainloop()
main()
And also I don't think I'm allowed to import tkinter, atleast I think that's what our prof said
Whenever you import the same module two different ways, you're already in trouble:
import turtle
from turtle import *
You're having problems distinguishing between the turtle and the screen -- using the above facilitates those problems. I recommend instead that you only use turtle's object-oriented interface and turn off the functional interface:
from turtle import Screen, Turtle
You're trying to use a turtle as a button, which is fine, but you put the click handler on the screen and had the handler test if you clicked the turtle. Instead, put the click handler on the turtle so you needn't test. (Again, part of the problem of not being clear about what the turtle does and what the screen does.)
Though you call it twice, listen() doesn't apply here as were not dealing with keyboard input (yet).
Finally, your color change handler updated the color index but never actually changed any colors. Below is my rework and simplification of your code to address the above issues:
from turtle import Screen, Turtle
COLOUR_LIST = ['black', 'blue', 'green', 'red', 'orange', 'purple']
colour_index = 0
def colour_change(x, y):
global colour_index
colour_index = (colour_index + 1) % len(COLOUR_LIST)
t1.color(COLOUR_LIST[colour_index])
def dragging(x, y):
t1.ondrag(None)
t1.setheading(t1.towards(x, y))
t1.goto(x, y)
t1.ondrag(dragging)
def click_right(x, y):
t1.clear()
t1 = Turtle('circle')
t1.shapesize(0.5)
t1.speed('fastest')
t1.color(COLOUR_LIST[colour_index])
t1.ondrag(dragging)
# changing colour turtle
tcolour = Turtle('square')
tcolour.penup()
tcolour.shapesize(1, 1.5)
tcolour.setpos(-275, 285)
tcolour.onclick(colour_change, 1)
screen = Screen()
screen.onclick(click_right, btn=3)
screen.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