Python Turtle Objects in conjuction with tkinter is it possible? - python

I'm having an issue when I run my main.py, it shows two screens. I know it's because I'm calling an object, just not sure if it's possible to use objects and have it show up on the tkinter window.
main.py
import tkinter as tk
from turtle import TurtleScreen
from createDotTest import Dot
top = tk.Tk()
canvas = tk.Canvas(top, width=600, height=600)
canvas.pack()
screen = TurtleScreen(canvas)
screen.tracer(0)
list_of_points = []
list_of_lines = []
for x in range(100):
dot = Dot()
list_of_points.append(dot)
screen.mainloop()
createDotTest.py
from turtle import Turtle
import random
class Dot(Turtle):
def __init__(self):
super().__init__()
x_pos = random.randint(-280, 280)
y_pos = random.randint(-280, 280)
self.shapesize(.2,.2)
self.penup()
self.shape('circle')
self.goto(x_pos, y_pos)
self.stamp()
I tried also replacing Turtle as TurtleRaw in the createDotTest.py but I get
raise TurtleGraphicsError("bad canvas argument %s" % canvas)
turtle.TurtleGraphicsError: bad canvas argument None

This question looks similar to Combine tkinter and turtle
I am not sure but this may help you

Related

Creating Turtle objects in a class with python

I am trying to create turtle objects with a class for my project which is a game. Each "Plane" object consists of:
plane3 = RawTurtle(screen)
plane3.ht()
plane3.color("red")
plane3.shape("plane.gif")
plane3.penup()
plane3.speed('fastest')
plane3.setposition(-270, 200)
plane3.setheading(360)
When putting this into a class and looking at other stack overflows questions to find out what to do, i threw together the following code:
class planes():
def __init__(self):
self.RawTurtle = RawTurtle(screen)
#self.hideturtle()
self.color = "red"
self.shape = ("plane.gif")
#self.penup()
self.speed = "fastest"
self.setposition = (-270, 100)
self.setheading = 360
Plane4 = planes()
When the code is run the turtle takes no shape or colour and is just a black triangle even though it causes no errors. However, errors do occur with the plane.hideturtle and plane.penup() functions which is why they are commented out.
File "C:/Users/marco/Desktop/Trooper shooter/TrooperShooter.py", line 694, in init
self.hideturtle()
AttributeError: 'planes' object has no attribute 'hideturtle'
Planes outside the class work perfectly and all planes are exactly identical. Any help is appreciated!
hideturtle() and penup() are both methods for the RawTurtle class, you haven't defined them for your planes class. So instead of this:
self.hideturtle()
self.penup()
you should have this:
self.RawTurtle.hideturtle()
self.RawTurtle.penup()
I believe your real problem is that your designed your plane class such that it has a turtle instead of designing it such that it is a turtle.
Taking the has a approach, every time you want to enable some additional turtle feature on your plane, you have to add a method to pass the call through to the contained turtle. Taking the is a approach, all turtle methods are in play:
from turtle import RawTurtle, TurtleScreen
from tkinter import Tk, Canvas, RIGHT
class Plane(RawTurtle):
def __init__(self):
super().__init__(screen)
self.hideturtle()
self.color('red')
self.shape('plane.gif')
# self.speed('fastest') # commented out while debugging
self.penup()
self.setposition(-270, 100)
self.setheading(0)
self.showturtle()
root = Tk()
canvas = Canvas(root, width=600, height=400)
canvas.pack(side=RIGHT)
screen = TurtleScreen(canvas)
screen.register_shape('plane.gif')
plane4 = Plane()
plane4.forward(400)
screen.mainloop()

How do I get mouse position with tkinter and turtle?

I am trying to make a program that lets me draw on a tkinter window using turtle. For some reason I cannot get the absolute mouse coordinates.
I have done root.winfo_pointerx() - root.winfo_rootx() (and vrootx).
I have also tried:
def mousePos(event):
x,y = event.x , event.y
return x,y
My code:
import turtle
import tkinter as tk
root = tk.Tk()
root.title("Draw!")
cv = tk.Canvas(root, width=500,height=500)
cv.focus_set()
cv.pack(side = tk.LEFT)
pen = turtle.RawTurtle(cv)
window = pen.getscreen()
def main():
window.setworldcoordinates(-500,-500,500,500)
window.bgcolor("white")
frame = tk.Frame(root)
frame.pack(side = tk.RIGHT,fill=tk.BOTH)
pointLabel = tk.Label(frame,text="Width")
pointLabel.pack()
def getPosition(event):
x = root.winfo_pointerx()-root.winfo_vrootx()
y = root.winfo_pointery()-root.winfo_vrooty()
pen.goto(x,y)
cv.bind("<Motion>", getPosition)
cv.pack
tk.mainloop()
pass
I want the cursor to be on top of the arrow, but instead it is always to the right and down. Also, when I move the mouse up, the arrow moves down, and vice versa.
Think hard about how you set the setworldcoordinate(). -500 - 500 means your world has 1,000 in size and window size is 500. Also, the mouse pointer offset from the window root - both absolute coordinates should be used. You mixed up the absolute coordinates - mouse pointer and vrootx which is in different scale so the distance of two makes no sense. Following code is probably closer to what you intended. Note that, I set the world coordinate to match the absolute coordinates of mouse pointer offset from the top/left corner of window.
import turtle
import tkinter as tk
root = tk.Tk()
root.title("Draw!")
cv = tk.Canvas(root, width=500,height=500)
cv.focus_set()
cv.pack(side = tk.LEFT)
pen = turtle.RawTurtle(cv)
window = pen.getscreen()
def main():
window.setworldcoordinates(0,500,500,0)
window.bgcolor("white")
frame = tk.Frame(root)
frame.pack(side = tk.RIGHT,fill=tk.BOTH)
pointLabel = tk.Label(frame,text="Width")
pointLabel.pack()
print(dir(root))
def getPosition(event):
x = root.winfo_pointerx()-root.winfo_rootx()
y = root.winfo_pointery()-root.winfo_rooty()
print(x, y)
pen.goto(x,y)
pass
cv.bind("<Motion>", getPosition)
cv.pack
tk.mainloop()
pass
if __name__ == "__main__":
main()
pass
You've got an issue working against you that isn't of your own making. The general rule is when in a turtle canvas, use turtle methods. But turtle doesn't have an inherent 'Motion' event type, so you were trying to use the raw Canvas one as a substitute. Thus the conflict.
An issue of your own making is that when you're inside a fast moving event handler, you need to disable the event hander as the first thing you do, reenabling on exit. Otherwise, events overlap and bad things happen. (Inadvertant recursions and other wierdness.)
I've rewritten your program below to work as I believe you intended. The fix is adding the missing turtle method so we can stay within the turtle domain:
import tkinter as tk
from turtle import RawTurtle, TurtleScreen
from functools import partial
def onscreenmove(self, fun, add=None): # method missing from turtle.py
if fun is None:
self.cv.unbind('<Motion>')
else:
def eventfun(event):
fun(self.cv.canvasx(event.x) / self.xscale, -self.cv.canvasy(event.y) / self.yscale)
self.cv.bind('<Motion>', eventfun, add)
def getPosition(x, y):
screen.onscreenmove(None) # disable events inside handler
pen.setheading(pen.towards(x, y))
pen.goto(x, y)
screen.onscreenmove(getPosition) # reenable handler on exit
root = tk.Tk()
root.title("Draw!")
cv = tk.Canvas(root, width=500, height=500)
cv.focus_set()
cv.pack(side=tk.LEFT)
screen = TurtleScreen(cv)
screen.onscreenmove = partial(onscreenmove, screen) # install missing method
pen = RawTurtle(screen)
frame = tk.Frame(root)
frame.pack(side=tk.RIGHT, fill=tk.BOTH)
tk.Label(frame, text="Width").pack()
screen.onscreenmove(getPosition)
screen.mainloop()
Mouse position for Tkinter:
import Tkinter as tk
root = tk.Tk()
def motion(event):
x, y = event.x, event.y
print('{}, {}'.format(x, y))
root.bind('<Motion>', motion)
root.mainloop()
Mouse position for turtle:
canvas = turtle.getcanvas()
x, y = canvas.winfo_pointerx(), canvas.winfo_pointery()
Hope this helps.

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

How to change the background color of RawTurtle

I wrote a python script, which should open a Tkinter window with a canvas and let turtle draw in this canvas. Now I want to change the background color of the canvas, but it stays always white (default settings of RawTurtle?). Is there any possibility to draw on a background with another color?
from Tkinter import *
import turtle
root = Tk()
root.overrideredirect(1)
ccanvas = Canvas(root, width = 800, height = 480)
ccanvas.pack()
turtle = turtle.RawTurtle(ccanvas)
turtle = turtle.bgcolor("black")
mainloop()
If I try turtle = turtle.bgcolor("black") the error looks like this: 'RawTurtle' object has no attribute 'bgcolor'.
You can supply a turtle.TurtleScreen (provides a bgcolor method) to turtle.RawTurtle instead of directly using Canvas :
ccanvas = Canvas(root, width = 800, height = 480)
turtle_screen = turtle.TurtleScreen(ccanvas)
turtle_screen.bgcolor("black")
ccanvas.pack()
turtle = turtle.RawTurtle(turtle_screen)
ccanvas.configure(background='black')

Categories

Resources