Implement Python tkinter zoom with turtle and single/double click - python

I am trying to draw turtle in canvas and I am also trying to implement zoom in zoom out feature with single click and double click event. When I am not trying to implement tkinter the code works absolutely fine but when I am trying to perform zoom in zoom out feature, I am unable to execute it. I would greatly appreciate any suggestions or help.
Here is my code:
import turtle
import tkinter as tk
from tkinter import *
root = tk.Tk()
canvas = tk.Canvas(master = root, width = 2700, height = 2500)
canvas.pack(fill=BOTH, expand=1)
mb = Menubutton(None, text='Mouse Clicks')
mb.pack()
t = turtle.RawTurtle(canvas)
def parallel():
window= canvas
def zoomin(event):
d = event.delta
if d < 0:
amt=0.9
else:
amt=1.1
canvas.scale(ALL, 2700,2500 , amt,amt)
mb.bind('<Button-1>', zoomin)
def zoomout(event1, d1, amt1):
d1 = event1.delta
if d1 >0:
amt1=1.1
else:
amt1=0.7
canvas.scale(ALL, 2700,2500 , amt, amt)
mb.bind('<Double-1>', zoomout)
t.pu()
t.left(90)
t.forward(70)
t.rt(90)
t.pd()
t.width(8)
t.color("LightGray")
t.forward(1200)
t.back(1200)
t.pu()
t.left(90)
t.forward(25)
t.rt(90)
t.pd()
t.forward(1200)
t.back(1200)
t.pu()
t.setposition(-85, 45)
t.pd()
t.forward(80)
t.left(90)
t.forward(80)
t.left(90)
t.forward(80)
t.left(90)
t.forward(80)
t.left(90)
t.penup()
t.goto(-200, 160)
t.write("Class", True, align="center", font=('TimesNewRoman', 20, 'normal'))
t.pendown()
t.penup()
t.goto(-45, 150)
t.write("1", True, align="center", font=('TimesNewRoman', 50, 'normal'))
t.pendown()
parallel()
t.mainloop()
Thank you.

Your program seems incomplete and structured incorrectly. Below is my minimalist example of what I believe you're trying to do. It draws a circle and then lets you use the mouse wheel to zoom it in and out:
import tkinter as tk
from turtle import RawTurtle, TurtleScreen, ScrolledCanvas
def zoom(event):
amount = 0.9 if event.delta < 0 else 1.1
canvas.scale(tk.ALL, 0, 0, amount, amount)
root = tk.Tk()
canvas = ScrolledCanvas(master=root, width=2000, height=2000)
canvas.pack(fill=tk.BOTH, expand=tk.YES)
screen = TurtleScreen(canvas)
turtle = RawTurtle(screen)
turtle.penup()
turtle.sety(-250)
turtle.pendown()
turtle.circle(250)
canvas.bind('<MouseWheel>', zoom)
screen.mainloop()
Note that certain turtle elements, like dot() and text generated with write() won't zoom, they'll remain fixed. You'll need to read about the .scale() method, and go deeper into tkinter, to potentially work around this. Or manually scale your fonts yourself.

Related

How to move objects diagonally in Tkinter's Canvas?

How can I make an object move diagonally in a Tkinter canvas every time someone presses two arrow keys at the same time?
I'm creating a simple animation but it only moves up, down, left or right.
Here's the code I have:
from tkinter import *
import time
root = Tk()
canvas = Canvas(root, width=800, height=800)
square = canvas.create_rectangle(0,0,50,50,outline='red')
def right(event):
for i in range(5):
canvas.move(ball,1,0)
canvas.update()
def left(event):
for i in range(5):
canvas.move(ball,-1,0)
canvas.update()
def down(event):
for i in range(5):
canvas.move(ball,0,1)
canvas.update()
def up(event):
for i in range(5):
canvas.move(ball,0,-1)
canvas.update()
root.bind('<Right>', right)
root.bind('<Left>', left)
root.bind('<Down>', down)
root.bind('<Up>', up)
canvas.pack()
root.mainloop()
Keypresses in tkinter are individual events; to the exception of key modifiers (shift, control, alt), you cannot bind an action to the "simultaneous" pressing of two keys.
What you can do, is assign NE, SE, NW, SW moves to different keys.
I assigned the control of the movements to the following keys:
Q W E
A D
Z X C
other changes:
It is best practice to avoid star imports.
It was not necessary to update the canvas each time; move already redraws the changes on the canvas.
I assigned a 'speed' to the object, removed the repeated calling of movein a loop, and use the speed to determine the distance to move.
I renamed square to ball, so ball is defined.
the code:
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=800, height=800)
ball = canvas.create_rectangle(0, 0, 50, 50, outline='red')
speed = 5
def w(event):
canvas.move(ball, speed, 0)
def e(event):
canvas.move(ball, -speed, 0)
def s(event):
canvas.move(ball, 0, speed)
def n(event):
canvas.move(ball, 0, -speed)
def nw(e):
canvas.move(ball, speed, -speed)
def sw(e):
canvas.move(ball, speed, speed)
def ne(e):
canvas.move(ball, -speed, -speed)
def se(e):
canvas.move(ball, -speed, speed)
root.bind('<KeyPress-w>', n)
root.bind('<KeyPress-e>', nw)
root.bind('<KeyPress-d>', w)
root.bind('<KeyPress-c>', sw)
root.bind('<KeyPress-x>', s)
root.bind('<KeyPress-z>', se)
root.bind('<KeyPress-a>', e)
root.bind('<KeyPress-q>', ne)
canvas.pack()
root.mainloop()

Turtle in Tkinter creating multiple windows

I am attempting to create a quick turtle display using Tkinter, but some odd things are happening.
First two turtle windows are being created, (one blank, one with the turtles), secondly, any attempt of turning the tracer off is not working.
This might be a simple fix but at the moment I cannot find it.
Any help would be appreciated,
Below is the code:
import tkinter as tk
import turtle
window = tk.Tk()
window.title('Top 10\'s')
def loadingscreen():
canvas = tk.Canvas(master = window, width = 500, height = 500)
canvas.pack()
arc1 = turtle.RawTurtle(canvas)
arc2 = turtle.RawTurtle(canvas)
#clean up the turtles and release the window
def cleanup():
turtle.tracer(True)
arc1.ht()
arc2.ht()
turtle.done()
#animate the turtles
def moveTurtles(rangevar,radius,extent,decrease):
for distance in range(rangevar):
arc1.circle(-radius,extent = extent)
arc2.circle(-radius,extent = extent)
radius -= decrease
#Set the turtle
def setTurtle(turt,x,y,heading,pensize,color):
turt.pu()
turt.goto(x,y)
turt.pd()
turt.seth(heading)
turt.pensize(pensize)
turt.pencolor(color)
#draw on the canvas
def draw():
#set variables
rangevar = 200
radius = 200
decrease = 1
extent = 2
#setup and draw the outline
turtle.tracer(False)
setTurtle(arc1,0,200,0,40,'grey')
setTurtle(arc2,14,-165,180,40,'grey')
moveTurtles(rangevar,radius,extent,decrease)
#setup and animate the logo
turtle.tracer(True)
setTurtle(arc1,0,200,0,20,'black')
setTurtle(arc2,14,-165,180,20,'black')
moveTurtles(rangevar,radius,extent,decrease)
#main program
def main():
turtle.tracer(False)
arc1.speed(0)
arc2.speed(0)
draw()
cleanup()
if __name__ == "__main__":
try:
main()
except:
print("An error occurred!!")
loadingscreen()
Essentially I am creating a Tk window, then a canvas, then two turtles, and then animating these turtles
My guess is you're trying to call turtle screen methods without actually having a turtle screen. When turtle is embedded in tkinter like this, you can overlay a Canvas with a TurtleScreen instance which will provide some, but not all, of the screen features of the standalone turtle:
import tkinter as tk
from turtle import RawTurtle, TurtleScreen
def cleanup():
""" hide the turtles """
arc1.hideturtle()
arc2.hideturtle()
def moveTurtles(rangevar, radius, extent, decrease):
""" animate the turtles """
for _ in range(rangevar):
arc1.circle(-radius, extent=extent)
arc2.circle(-radius, extent=extent)
radius -= decrease
def setTurtle(turtle, x, y, heading, pensize, color):
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
turtle.setheading(heading)
turtle.pensize(pensize)
turtle.pencolor(color)
def draw():
# set variables
rangevar = 200
radius = 200
decrease = 1
extent = 2
screen.tracer(False) # turn off animation while drawing outline
# setup and draw the outline
setTurtle(arc1, 0, 200, 0, 40, 'grey')
setTurtle(arc2, 14, -165, 180, 40, 'grey')
moveTurtles(rangevar, radius, extent, decrease)
screen.tracer(True) # turn animation back on for the following
# setup and animate the logo
setTurtle(arc1, 0, 200, 0, 20, 'black')
setTurtle(arc2, 14, -165, 180, 20, 'black')
moveTurtles(rangevar, radius, extent, decrease)
# main program
window = tk.Tk()
window.title("Top 10's")
canvas = tk.Canvas(master=window, width=500, height=500)
canvas.pack()
screen = TurtleScreen(canvas)
arc1 = RawTurtle(screen)
arc1.speed('fastest')
arc2 = RawTurtle(screen)
arc2.speed('fastest')
draw()
cleanup()
Another suggestion: don't mess with tracer() until after everything else is working and then (re)read it's documentation carefully.
I just have the answer for the two windows that are being created: the one with the turtles is obvious, and the blank one is for the main root window that you define (window = tk.Tk()). If you want it not to appear at all, you can add the following line right after its definition:
window.withdraw()
I found this solution here and here.

How do I get data from tkinter and add it into turtle?

I've been trying to tkinters .Entry command and use the user input to put into turtle, but I keep getting an error:
In my case, I am trying to ask the user for a color that they want to use in turtle.
My code:
import tkinter
from turtle import Turtle
#Create and Format window
w = tkinter.Tk()
w.title("Getting To Know You")
w.geometry("400x200")
#Favorite Color
lbl3= tkinter.Label(w, text = "What's your favorite color?")
lbl3.grid(row = 10 , column = 2)
olor = tkinter.Entry(w)
olor.grid(row = 12, column = 2)
t = Turtle()
t.begin_fill()
t.color(olor)
shape = int (input ("What is your favorite shape?"))
w.mainloop()
My recommendation is you work within turtle completely and not drop down to the tkinter level:
from turtle import Turtle, Screen
# Create and Format window
screen = Screen()
screen.setup(400, 200)
screen.title("Getting To Know You")
# Favorite Color
color = screen.textinput("Choose a color", "What's your favorite color?")
turtle = Turtle()
turtle.color(color)
turtle.begin_fill()
turtle.circle(25)
turtle.end_fill()
turtle.hideturtle()
screen.mainloop()
If you must do this from tkinter, you need to read more about tkinter elements like Entry to know their capabilities. You also need to read more about turtle as it is invoked differently when embedded inside of a tkinter window. Here's a rough approximation of what you're trying to do:
import tkinter as tk
from turtle import RawTurtle, TurtleScreen, ScrolledCanvas
root = tk.Tk()
root.geometry("400x200")
root.title("Getting To Know You")
def draw_circle():
turtle.color(color_entry.get())
turtle.begin_fill()
turtle.circle(25)
turtle.end_fill()
# Favorite Color
tk.Label(root, text="What's your favorite color?").pack()
color_entry = tk.Entry(root)
color_entry.pack()
tk.Button(root, text='Draw Circle', command=draw_circle).pack()
canvas = ScrolledCanvas(root)
canvas.pack(fill=tk.BOTH, expand=tk.YES)
screen = TurtleScreen(canvas)
turtle = RawTurtle(screen, visible=False)
screen.mainloop()

Moving a shaper using mouse click in Tkinter

I want to make a shape move left if I leftclick my mouse , and go right if I click right. The following code is not working. What have I done wrong ?
from tkinter import *
import time
tk =Tk()
canvas = Canvas(tk, width=500, height=500,)
tk.title("Drawing")
xbat = 0
def clickL(event):
xbat =- 1
print(xbat)
def clickR(event):
xbat =+ 1
print(xbat)
canvas.bind("<Button-1>", clickL)
canvas.bind("<Button-3>", clickR)
canvas.pack()
bat = canvas.create_rectangle(150, 500, 300, 480, fill="black")
while True:
canvas.move(bat,xbat,0)
tk.update()
time.sleep(0.01)
canvas.mainloop()
Try this
from tkinter import *
tk =Tk()
canvas = Canvas(tk, width=500, height=500,)
tk.title("Drawing")
def clickL(event):
xbat = -1
print(xbat)
xmove(bat,xbat)
def clickR(event):
xbat = 1
print(xbat)
xmove(bat,xbat)
def xmove(object,x):
canvas.move(object,x,0)
canvas.bind("<Button-1>", clickL)
canvas.bind("<Button-3>", clickR)
canvas.pack()
bat = canvas.create_rectangle(150, 500, 300, 480, fill="black")
canvas.mainloop()
It is typically bad practice to have a while True loop in tkinter code, it doesn't give the GUI time to update. Instead I've changed you code so that each click event calls a separate xmove function.
An alternative approach could be to change the coordinate of the object when the button is clicked then have a periodic update function which re-draws/moves the objects to their update positions. This periodic update could be achieved with the tkinter .after method.

Turtle freehand drawing

I'm working on a simple drawing program that combines Tkinter and Turtle modules.
I would like to add an option that the user can draw anything by just using mouse similar to pen widget on Paint. I tried many things, I could not figure out how l can do it.How can l make the turtle draw anything (like pen widget on Paint ) on canvas by using mouse
from tkinter import *
import turtle
sc=Tk()
sc.geometry("1000x1000+100+100")
fr4=Frame(sc,height=500,width=600,bd=4,bg="light green",takefocus="",relief=SUNKEN)
fr4.grid(row=2,column=2,sticky=(N,E,W,S))
#Canvas
canvas = Canvas(fr4,width=750, height=750)
canvas.pack()
#Turtle
turtle1=turtle.RawTurtle(canvas)
turtle1.color("blue")
turtle1.shape("turtle")
points=[]
spline=0
tag1="theline"
def point(event):
canvas.create_oval(event.x, event.y, event.x+1, event.y+1, fill="red")
points.append(event.x)
points.append(event.y)
return points
def canxy(event):
print (event.x, event.y)
def graph(event):
global theline
canvas.create_line(points, tags="theline")
def toggle(event):
global spline
if spline == 0:
canvas.itemconfigure(tag1, smooth=1)
spline = 1
elif spline == 1:
canvas.itemconfigure(tag1, smooth=0)
spline = 0
return spline
canvas.bind("<Button-1>", point)
canvas.bind("<Button-3>", graph)
canvas.bind("<Button-2>", toggle)
sc.mainloop()
The following code will let you freehand draw with the turtle. You'll need to integrate with the rest of your code:
import tkinter
import turtle
sc = tkinter.Tk()
sc.geometry("1000x1000+100+100")
fr4 = tkinter.Frame(sc, height=500, width=600, bd=4, bg="light green", takefocus="", relief=tkinter.SUNKEN)
fr4.grid(row=2, column=2, sticky=(tkinter.N, tkinter.E, tkinter.W, tkinter.S))
# Canvas
canvas = tkinter.Canvas(fr4, width=750, height=750)
canvas.pack()
# Turtle
turtle1 = turtle.RawTurtle(canvas)
turtle1.color("blue")
turtle1.shape("turtle")
def drag_handler(x, y):
turtle1.ondrag(None) # disable event inside event handler
turtle1.goto(x, y)
turtle1.ondrag(drag_handler) # reenable event on event handler exit
turtle1.ondrag(drag_handler)
sc.mainloop()

Categories

Resources