2 # turtle.py: a Tkinter based turtle graphics module for Python
3 # Version 1.0.1 - 24. 9. 2009
5 # Copyright (C) 2006 - 2009 Gregor Lingl
8 # This software is provided 'as-is', without any express or implied
9 # warranty. In no event will the authors be held liable for any damages
10 # arising from the use of this software.
12 # Permission is granted to anyone to use this software for any purpose,
13 # including commercial applications, and to alter it and redistribute it
14 # freely, subject to the following restrictions:
16 # 1. The origin of this software must not be misrepresented; you must not
17 # claim that you wrote the original software. If you use this software
18 # in a product, an acknowledgment in the product documentation would be
19 # appreciated but is not required.
20 # 2. Altered source versions must be plainly marked as such, and must not be
21 # misrepresented as being the original software.
22 # 3. This notice may not be removed or altered from any source distribution.
26 Turtle graphics is a popular way for introducing programming to
27 kids. It was part of the original Logo programming language developed
28 by Wally Feurzig and Seymour Papert in 1966.
30 Imagine a robotic turtle starting at (0, 0) in the x-y plane. Give it
31 the command turtle.forward(15), and it moves (on-screen!) 15 pixels in
32 the direction it is facing, drawing a line as it moves. Give it the
33 command turtle.left(25), and it rotates in-place 25 degrees clockwise.
35 By combining together these and similar commands, intricate shapes and
36 pictures can easily be drawn.
40 This module is an extended reimplementation of turtle.py from the
41 Python standard distribution up to Python 2.5. (See: http://www.python.org)
43 It tries to keep the merits of turtle.py and to be (nearly) 100%
44 compatible with it. This means in the first place to enable the
45 learning programmer to use all the commands, classes and methods
46 interactively when using the module from within IDLE run with
49 Roughly it has the following features added:
51 - Better animation of the turtle movements, especially of turning the
52 turtle. So the turtles can more easily be used as a visual feedback
53 instrument by the (beginning) programmer.
55 - Different turtle shapes, gif-images as turtle shapes, user defined
56 and user controllable turtle shapes, among them compound
57 (multicolored) shapes. Turtle shapes can be stretched and tilted, which
58 makes turtles very versatile geometrical objects.
60 - Fine control over turtle movement and screen updates via delay(),
61 and enhanced tracer() and speed() methods.
63 - Aliases for the most commonly used commands, like fd for forward etc.,
64 following the early Logo traditions. This reduces the boring work of
65 typing long sequences of commands, which often occur in a natural way
66 when kids try to program fancy pictures on their first encounter with
69 - Turtles now have an undo()-method with configurable undo-buffer.
71 - Some simple commands/methods for creating event driven programs
72 (mouse-, key-, timer-events). Especially useful for programming games.
74 - A scrollable Canvas class. The default scrollable Canvas can be
75 extended interactively as needed while playing around with the turtle(s).
77 - A TurtleScreen class with methods controlling background color or
78 background image, window and canvas size and other properties of the
81 - There is a method, setworldcoordinates(), to install a user defined
82 coordinate-system for the TurtleScreen.
84 - The implementation uses a 2-vector class named Vec2D, derived from tuple.
85 This class is public, so it can be imported by the application programmer,
86 which makes certain types of computations very natural and compact.
88 - Appearance of the TurtleScreen and the Turtles at startup/import can be
89 configured by means of a turtle.cfg configuration file.
90 The default configuration mimics the appearance of the old turtle module.
92 - If configured appropriately the module reads in docstrings from a docstring
93 dictionary in some different language, supplied separately and replaces
94 the English ones by those read in. There is a utility function
95 write_docstringdict() to write a dictionary with the original (English)
96 docstrings to disc, so it can serve as a template for translations.
98 Behind the scenes there are some features included with possible
99 extensions in in mind. These will be commented and documented elsewhere.
103 _ver
= "turtle 1.0b1 - for Python 2.6 - 30. 5. 2008, 18:08"
113 from os
.path
import isfile
, split
, join
114 from copy
import deepcopy
116 from math
import * ## for compatibility with old turtle module
118 _tg_classes
= ['ScrolledCanvas', 'TurtleScreen', 'Screen',
119 'RawTurtle', 'Turtle', 'RawPen', 'Pen', 'Shape', 'Vec2D']
120 _tg_screen_functions
= ['addshape', 'bgcolor', 'bgpic', 'bye',
121 'clearscreen', 'colormode', 'delay', 'exitonclick', 'getcanvas',
122 'getshapes', 'listen', 'mode', 'onkey', 'onscreenclick', 'ontimer',
123 'register_shape', 'resetscreen', 'screensize', 'setup',
124 'setworldcoordinates', 'title', 'tracer', 'turtles', 'update',
125 'window_height', 'window_width']
126 _tg_turtle_functions
= ['back', 'backward', 'begin_fill', 'begin_poly', 'bk',
127 'circle', 'clear', 'clearstamp', 'clearstamps', 'clone', 'color',
128 'degrees', 'distance', 'dot', 'down', 'end_fill', 'end_poly', 'fd',
129 'fill', 'fillcolor', 'forward', 'get_poly', 'getpen', 'getscreen',
130 'getturtle', 'goto', 'heading', 'hideturtle', 'home', 'ht', 'isdown',
131 'isvisible', 'left', 'lt', 'onclick', 'ondrag', 'onrelease', 'pd',
132 'pen', 'pencolor', 'pendown', 'pensize', 'penup', 'pos', 'position',
133 'pu', 'radians', 'right', 'reset', 'resizemode', 'rt',
134 'seth', 'setheading', 'setpos', 'setposition', 'settiltangle',
135 'setundobuffer', 'setx', 'sety', 'shape', 'shapesize', 'showturtle',
136 'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'towards', 'tracer',
137 'turtlesize', 'undo', 'undobufferentries', 'up', 'width',
138 'window_height', 'window_width', 'write', 'xcor', 'ycor']
139 _tg_utilities
= ['write_docstringdict', 'done', 'mainloop']
140 _math_functions
= ['acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh',
141 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
142 'log10', 'modf', 'pi', 'pow', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
144 __all__
= (_tg_classes
+ _tg_screen_functions
+ _tg_turtle_functions
+
145 _tg_utilities
+ _math_functions
)
147 _alias_list
= ['addshape', 'backward', 'bk', 'fd', 'ht', 'lt', 'pd', 'pos',
148 'pu', 'rt', 'seth', 'setpos', 'setposition', 'st',
149 'turtlesize', 'up', 'width']
151 _CFG
= {"width" : 0.5, # Screen
157 "mode": "standard", # TurtleScreen
160 "undobuffersize": 1000, # RawTurtle
162 "pencolor" : "black",
163 "fillcolor" : "black",
164 "resizemode" : "noresize",
166 "language": "english", # docstrings
167 "exampleturtle": "turtle",
168 "examplescreen": "screen",
169 "title": "Python Turtle Graphics",
173 ##print "cwd:", os.getcwd()
174 ##print "__file__:", __file__
176 ##def show(dictionary):
177 ## print "=========================="
178 ## for key in sorted(dictionary.keys()):
179 ## print key, ":", dictionary[key]
180 ## print "=========================="
183 def config_dict(filename
):
184 """Convert content of config-file into dictionary."""
185 f
= open(filename
, "r")
186 cfglines
= f
.readlines()
189 for line
in cfglines
:
191 if not line
or line
.startswith("#"):
194 key
, value
= line
.split("=")
196 print "Bad line in config-file %s:\n%s" % (filename
,line
)
199 value
= value
.strip()
200 if value
in ["True", "False", "None", "''", '""']:
209 pass # value need not be converted
213 def readconfig(cfgdict
):
214 """Read config-files, change configuration-dict accordingly.
216 If there is a turtle.cfg file in the current working directory,
217 read it from there. If this contains an importconfig-value,
218 say 'myway', construct filename turtle_mayway.cfg else use
219 turtle.cfg and read it from the import-directory, where
220 turtle.py is located.
221 Update configuration dictionary first according to config-file,
222 in the import directory, then according to config-file in the
223 current working directory.
224 If no config-file is found, the default configuration is used.
226 default_cfg
= "turtle.cfg"
229 if isfile(default_cfg
):
230 cfgdict1
= config_dict(default_cfg
)
231 #print "1. Loading config-file %s from: %s" % (default_cfg, os.getcwd())
232 if "importconfig" in cfgdict1
:
233 default_cfg
= "turtle_%s.cfg" % cfgdict1
["importconfig"]
235 head
, tail
= split(__file__
)
236 cfg_file2
= join(head
, default_cfg
)
239 if isfile(cfg_file2
):
240 #print "2. Loading config-file %s:" % cfg_file2
241 cfgdict2
= config_dict(cfg_file2
)
244 _CFG
.update(cfgdict2
)
247 _CFG
.update(cfgdict1
)
253 print "No configfile read, reason unknown"
257 """A 2 dimensional vector class, used as a helper class
258 for implementing turtle graphics.
259 May be useful for turtle graphics programs also.
260 Derived from tuple, so a vector is a tuple!
262 Provides (for a, b vectors, k number):
264 a-b vector subtraction
266 k*a and a*k multiplication with scalar
267 |a| absolute value of a
268 a.rotate(angle) rotation
270 def __new__(cls
, x
, y
):
271 return tuple.__new
__(cls
, (x
, y
))
272 def __add__(self
, other
):
273 return Vec2D(self
[0]+other
[0], self
[1]+other
[1])
274 def __mul__(self
, other
):
275 if isinstance(other
, Vec2D
):
276 return self
[0]*other
[0]+self
[1]*other
[1]
277 return Vec2D(self
[0]*other
, self
[1]*other
)
278 def __rmul__(self
, other
):
279 if isinstance(other
, int) or isinstance(other
, float):
280 return Vec2D(self
[0]*other
, self
[1]*other
)
281 def __sub__(self
, other
):
282 return Vec2D(self
[0]-other
[0], self
[1]-other
[1])
284 return Vec2D(-self
[0], -self
[1])
286 return (self
[0]**2 + self
[1]**2)**0.5
287 def rotate(self
, angle
):
288 """rotate self counterclockwise by angle
290 perp
= Vec2D(-self
[1], self
[0])
291 angle
= angle
* math
.pi
/ 180.0
292 c
, s
= math
.cos(angle
), math
.sin(angle
)
293 return Vec2D(self
[0]*c
+perp
[0]*s
, self
[1]*c
+perp
[1]*s
)
294 def __getnewargs__(self
):
295 return (self
[0], self
[1])
297 return "(%.2f,%.2f)" % self
300 ##############################################################################
301 ### From here up to line : Tkinter - Interface for turtle.py ###
302 ### May be replaced by an interface to some different graphics toolkit ###
303 ##############################################################################
305 ## helper functions for Scrolled Canvas, to forward Canvas-methods
306 ## to ScrolledCanvas class
308 def __methodDict(cls
, _dict
):
309 """helper function for Scrolled Canvas"""
310 baseList
= list(cls
.__bases
__)
312 for _super
in baseList
:
313 __methodDict(_super
, _dict
)
314 for key
, value
in cls
.__dict
__.items():
315 if type(value
) == types
.FunctionType
:
319 """helper function for Scrolled Canvas"""
321 __methodDict(cls
, _dict
)
325 'def %(method)s(self, *args, **kw): return ' +
326 'self.%(attribute)s.%(method)s(*args, **kw)')
328 def __forwardmethods(fromClass
, toClass
, toPart
, exclude
= ()):
329 """Helper functions for Scrolled Canvas, used to forward
330 ScrolledCanvas-methods to Tkinter.Canvas class.
333 __methodDict(toClass
, _dict
)
334 for ex
in _dict
.keys():
335 if ex
[:1] == '_' or ex
[-1:] == '_':
340 for ex
in __methods(fromClass
):
344 for method
, func
in _dict
.items():
345 d
= {'method': method
, 'func': func
}
346 if type(toPart
) == types
.StringType
:
348 __stringBody
% {'method' : method
, 'attribute' : toPart
}
350 fromClass
.__dict
__[method
] = d
[method
]
353 class ScrolledCanvas(TK
.Frame
):
354 """Modeled after the scrolled canvas class from Grayons's Tkinter book.
356 Used as the default canvas, which pops up automatically when
357 using turtle graphics functions or the Turtle class.
359 def __init__(self
, master
, width
=500, height
=350,
360 canvwidth
=600, canvheight
=500):
361 TK
.Frame
.__init
__(self
, master
, width
=width
, height
=height
)
362 self
._rootwindow
= self
.winfo_toplevel()
363 self
.width
, self
.height
= width
, height
364 self
.canvwidth
, self
.canvheight
= canvwidth
, canvheight
366 self
._canvas
= TK
.Canvas(master
, width
=width
, height
=height
,
367 bg
=self
.bg
, relief
=TK
.SUNKEN
, borderwidth
=2)
368 self
.hscroll
= TK
.Scrollbar(master
, command
=self
._canvas
.xview
,
369 orient
=TK
.HORIZONTAL
)
370 self
.vscroll
= TK
.Scrollbar(master
, command
=self
._canvas
.yview
)
371 self
._canvas
.configure(xscrollcommand
=self
.hscroll
.set,
372 yscrollcommand
=self
.vscroll
.set)
373 self
.rowconfigure(0, weight
=1, minsize
=0)
374 self
.columnconfigure(0, weight
=1, minsize
=0)
375 self
._canvas
.grid(padx
=1, in_
= self
, pady
=1, row
=0,
376 column
=0, rowspan
=1, columnspan
=1, sticky
='news')
377 self
.vscroll
.grid(padx
=1, in_
= self
, pady
=1, row
=0,
378 column
=1, rowspan
=1, columnspan
=1, sticky
='news')
379 self
.hscroll
.grid(padx
=1, in_
= self
, pady
=1, row
=1,
380 column
=0, rowspan
=1, columnspan
=1, sticky
='news')
382 self
._rootwindow
.bind('<Configure>', self
.onResize
)
384 def reset(self
, canvwidth
=None, canvheight
=None, bg
= None):
385 """Adjust canvas and scrollbars according to given canvas size."""
387 self
.canvwidth
= canvwidth
389 self
.canvheight
= canvheight
392 self
._canvas
.config(bg
=bg
,
393 scrollregion
=(-self
.canvwidth
//2, -self
.canvheight
//2,
394 self
.canvwidth
//2, self
.canvheight
//2))
395 self
._canvas
.xview_moveto(0.5*(self
.canvwidth
- self
.width
+ 30) /
397 self
._canvas
.yview_moveto(0.5*(self
.canvheight
- self
.height
+ 30) /
402 def adjustScrolls(self
):
403 """ Adjust scrollbars according to window- and canvas-size.
405 cwidth
= self
._canvas
.winfo_width()
406 cheight
= self
._canvas
.winfo_height()
407 self
._canvas
.xview_moveto(0.5*(self
.canvwidth
-cwidth
)/self
.canvwidth
)
408 self
._canvas
.yview_moveto(0.5*(self
.canvheight
-cheight
)/self
.canvheight
)
409 if cwidth
< self
.canvwidth
or cheight
< self
.canvheight
:
410 self
.hscroll
.grid(padx
=1, in_
= self
, pady
=1, row
=1,
411 column
=0, rowspan
=1, columnspan
=1, sticky
='news')
412 self
.vscroll
.grid(padx
=1, in_
= self
, pady
=1, row
=0,
413 column
=1, rowspan
=1, columnspan
=1, sticky
='news')
415 self
.hscroll
.grid_forget()
416 self
.vscroll
.grid_forget()
418 def onResize(self
, event
):
419 """self-explanatory"""
422 def bbox(self
, *args
):
423 """ 'forward' method, which canvas itself has inherited...
425 return self
._canvas
.bbox(*args
)
427 def cget(self
, *args
, **kwargs
):
428 """ 'forward' method, which canvas itself has inherited...
430 return self
._canvas
.cget(*args
, **kwargs
)
432 def config(self
, *args
, **kwargs
):
433 """ 'forward' method, which canvas itself has inherited...
435 self
._canvas
.config(*args
, **kwargs
)
437 def bind(self
, *args
, **kwargs
):
438 """ 'forward' method, which canvas itself has inherited...
440 self
._canvas
.bind(*args
, **kwargs
)
442 def unbind(self
, *args
, **kwargs
):
443 """ 'forward' method, which canvas itself has inherited...
445 self
._canvas
.unbind(*args
, **kwargs
)
447 def focus_force(self
):
448 """ 'forward' method, which canvas itself has inherited...
450 self
._canvas
.focus_force()
452 __forwardmethods(ScrolledCanvas
, TK
.Canvas
, '_canvas')
456 """Root class for Screen based on Tkinter."""
460 def setupcanvas(self
, width
, height
, cwidth
, cheight
):
461 self
._canvas
= ScrolledCanvas(self
, width
, height
, cwidth
, cheight
)
462 self
._canvas
.pack(expand
=1, fill
="both")
464 def _getcanvas(self
):
467 def set_geometry(self
, width
, height
, startx
, starty
):
468 self
.geometry("%dx%d%+d%+d"%(width
, height
, startx
, starty
))
470 def ondestroy(self
, destroy
):
471 self
.wm_protocol("WM_DELETE_WINDOW", destroy
)
474 return self
.winfo_screenwidth()
476 def win_height(self
):
477 return self
.winfo_screenheight()
482 class TurtleScreenBase(object):
483 """Provide the basic graphics functionality.
484 Interface between Tkinter and turtle.py.
486 To port turtle.py to some different graphics toolkit
487 a corresponding TurtleScreenBase class has to be implemented.
492 """return a blank image object
494 img
= TK
.PhotoImage(width
=1, height
=1)
499 def _image(filename
):
500 """return an image object containing the
501 imagedata from a gif-file named filename.
503 return TK
.PhotoImage(file=filename
)
505 def __init__(self
, cv
):
507 if isinstance(cv
, ScrolledCanvas
):
508 w
= self
.cv
.canvwidth
509 h
= self
.cv
.canvheight
510 else: # expected: ordinary TK.Canvas
511 w
= int(self
.cv
.cget("width"))
512 h
= int(self
.cv
.cget("height"))
513 self
.cv
.config(scrollregion
= (-w
//2, -h
//2, w
//2, h
//2 ))
516 self
.xscale
= self
.yscale
= 1.0
518 def _createpoly(self
):
519 """Create an invisible polygon item on canvas self.cv)
521 return self
.cv
.create_polygon((0, 0, 0, 0, 0, 0), fill
="", outline
="")
523 def _drawpoly(self
, polyitem
, coordlist
, fill
=None,
524 outline
=None, width
=None, top
=False):
525 """Configure polygonitem polyitem according to provided
527 coordlist is sequence of coordinates
528 fill is filling color
529 outline is outline color
530 top is a boolean value, which specifies if polyitem
531 will be put on top of the canvas' displaylist so it
532 will not be covered by other items.
535 for x
, y
in coordlist
:
536 cl
.append(x
* self
.xscale
)
537 cl
.append(-y
* self
.yscale
)
538 self
.cv
.coords(polyitem
, *cl
)
540 self
.cv
.itemconfigure(polyitem
, fill
=fill
)
541 if outline
is not None:
542 self
.cv
.itemconfigure(polyitem
, outline
=outline
)
543 if width
is not None:
544 self
.cv
.itemconfigure(polyitem
, width
=width
)
546 self
.cv
.tag_raise(polyitem
)
548 def _createline(self
):
549 """Create an invisible line item on canvas self.cv)
551 return self
.cv
.create_line(0, 0, 0, 0, fill
="", width
=2,
554 def _drawline(self
, lineitem
, coordlist
=None,
555 fill
=None, width
=None, top
=False):
556 """Configure lineitem according to provided arguments:
557 coordlist is sequence of coordinates
558 fill is drawing color
559 width is width of drawn line.
560 top is a boolean value, which specifies if polyitem
561 will be put on top of the canvas' displaylist so it
562 will not be covered by other items.
564 if coordlist
is not None:
566 for x
, y
in coordlist
:
567 cl
.append(x
* self
.xscale
)
568 cl
.append(-y
* self
.yscale
)
569 self
.cv
.coords(lineitem
, *cl
)
571 self
.cv
.itemconfigure(lineitem
, fill
=fill
)
572 if width
is not None:
573 self
.cv
.itemconfigure(lineitem
, width
=width
)
575 self
.cv
.tag_raise(lineitem
)
577 def _delete(self
, item
):
578 """Delete graphics item from canvas.
579 If item is"all" delete all graphics items.
584 """Redraw graphics items on canvas
588 def _delay(self
, delay
):
589 """Delay subsequent canvas actions for delay ms."""
592 def _iscolorstring(self
, color
):
593 """Check if the string color is a legal Tkinter color string.
596 rgb
= self
.cv
.winfo_rgb(color
)
602 def _bgcolor(self
, color
=None):
603 """Set canvas' backgroundcolor if color is not None,
604 else return backgroundcolor."""
605 if color
is not None:
606 self
.cv
.config(bg
= color
)
609 return self
.cv
.cget("bg")
611 def _write(self
, pos
, txt
, align
, font
, pencolor
):
612 """Write txt at pos in canvas with specified font
614 Return text item and x-coord of right bottom corner
615 of text's bounding box."""
619 anchor
= {"left":"sw", "center":"s", "right":"se" }
620 item
= self
.cv
.create_text(x
-1, -y
, text
= txt
, anchor
= anchor
[align
],
621 fill
= pencolor
, font
= font
)
622 x0
, y0
, x1
, y1
= self
.cv
.bbox(item
)
626 ## def _dot(self, pos, size, color):
627 ## """may be implemented for some other graphics toolkit"""
629 def _onclick(self
, item
, fun
, num
=1, add
=None):
630 """Bind fun to mouse-click event on turtle.
631 fun must be a function with two arguments, the coordinates
632 of the clicked point on the canvas.
633 num, the number of the mouse-button defaults to 1
636 self
.cv
.tag_unbind(item
, "<Button-%s>" % num
)
639 x
, y
= (self
.cv
.canvasx(event
.x
)/self
.xscale
,
640 -self
.cv
.canvasy(event
.y
)/self
.yscale
)
642 self
.cv
.tag_bind(item
, "<Button-%s>" % num
, eventfun
, add
)
644 def _onrelease(self
, item
, fun
, num
=1, add
=None):
645 """Bind fun to mouse-button-release event on turtle.
646 fun must be a function with two arguments, the coordinates
647 of the point on the canvas where mouse button is released.
648 num, the number of the mouse-button defaults to 1
650 If a turtle is clicked, first _onclick-event will be performed,
651 then _onscreensclick-event.
654 self
.cv
.tag_unbind(item
, "<Button%s-ButtonRelease>" % num
)
657 x
, y
= (self
.cv
.canvasx(event
.x
)/self
.xscale
,
658 -self
.cv
.canvasy(event
.y
)/self
.yscale
)
660 self
.cv
.tag_bind(item
, "<Button%s-ButtonRelease>" % num
,
663 def _ondrag(self
, item
, fun
, num
=1, add
=None):
664 """Bind fun to mouse-move-event (with pressed mouse button) on turtle.
665 fun must be a function with two arguments, the coordinates of the
666 actual mouse position on the canvas.
667 num, the number of the mouse-button defaults to 1
669 Every sequence of mouse-move-events on a turtle is preceded by a
670 mouse-click event on that turtle.
673 self
.cv
.tag_unbind(item
, "<Button%s-Motion>" % num
)
677 x
, y
= (self
.cv
.canvasx(event
.x
)/self
.xscale
,
678 -self
.cv
.canvasy(event
.y
)/self
.yscale
)
682 self
.cv
.tag_bind(item
, "<Button%s-Motion>" % num
, eventfun
, add
)
684 def _onscreenclick(self
, fun
, num
=1, add
=None):
685 """Bind fun to mouse-click event on canvas.
686 fun must be a function with two arguments, the coordinates
687 of the clicked point on the canvas.
688 num, the number of the mouse-button defaults to 1
690 If a turtle is clicked, first _onclick-event will be performed,
691 then _onscreensclick-event.
694 self
.cv
.unbind("<Button-%s>" % num
)
697 x
, y
= (self
.cv
.canvasx(event
.x
)/self
.xscale
,
698 -self
.cv
.canvasy(event
.y
)/self
.yscale
)
700 self
.cv
.bind("<Button-%s>" % num
, eventfun
, add
)
702 def _onkey(self
, fun
, key
):
703 """Bind fun to key-release event of key.
704 Canvas must have focus. See method listen
707 self
.cv
.unbind("<KeyRelease-%s>" % key
, None)
711 self
.cv
.bind("<KeyRelease-%s>" % key
, eventfun
)
714 """Set focus on canvas (in order to collect key-events)
716 self
.cv
.focus_force()
718 def _ontimer(self
, fun
, t
):
719 """Install a timer, which calls fun after t milliseconds.
722 self
.cv
.after_idle(fun
)
724 self
.cv
.after(t
, fun
)
726 def _createimage(self
, image
):
727 """Create and return image item on canvas.
729 return self
.cv
.create_image(0, 0, image
=image
)
731 def _drawimage(self
, item
, (x
, y
), image
):
732 """Configure image item as to draw image object
733 at position (x,y) on canvas)
735 self
.cv
.coords(item
, (x
* self
.xscale
, -y
* self
.yscale
))
736 self
.cv
.itemconfig(item
, image
=image
)
738 def _setbgpic(self
, item
, image
):
739 """Configure image item as to draw image object
740 at center of canvas. Set item to the first item
741 in the displaylist, so it will be drawn below
743 self
.cv
.itemconfig(item
, image
=image
)
744 self
.cv
.tag_lower(item
)
746 def _type(self
, item
):
747 """Return 'line' or 'polygon' or 'image' depending on
750 return self
.cv
.type(item
)
752 def _pointlist(self
, item
):
753 """returns list of coordinate-pairs of points of item
754 Example (for insiders):
755 >>> from turtle import *
756 >>> getscreen()._pointlist(getturtle().turtle._item)
757 [(0.0, 9.9999999999999982), (0.0, -9.9999999999999982),
758 (9.9999999999999982, 0.0)]
760 cl
= self
.cv
.coords(item
)
761 pl
= [(cl
[i
], -cl
[i
+1]) for i
in range(0, len(cl
), 2)]
764 def _setscrollregion(self
, srx1
, sry1
, srx2
, sry2
):
765 self
.cv
.config(scrollregion
=(srx1
, sry1
, srx2
, sry2
))
767 def _rescale(self
, xscalefactor
, yscalefactor
):
768 items
= self
.cv
.find_all()
770 coordinates
= self
.cv
.coords(item
)
773 x
, y
= coordinates
[:2]
774 newcoordlist
.append(x
* xscalefactor
)
775 newcoordlist
.append(y
* yscalefactor
)
776 coordinates
= coordinates
[2:]
777 self
.cv
.coords(item
, *newcoordlist
)
779 def _resize(self
, canvwidth
=None, canvheight
=None, bg
=None):
780 """Resize the canvas the turtles are drawing on. Does
781 not alter the drawing window.
784 if not isinstance(self
.cv
, ScrolledCanvas
):
785 return self
.canvwidth
, self
.canvheight
786 if canvwidth
is None and canvheight
is None and bg
is None:
787 return self
.cv
.canvwidth
, self
.cv
.canvheight
788 if canvwidth
is not None:
789 self
.canvwidth
= canvwidth
790 if canvheight
is not None:
791 self
.canvheight
= canvheight
792 self
.cv
.reset(canvwidth
, canvheight
, bg
)
794 def _window_size(self
):
795 """ Return the width and height of the turtle window.
797 width
= self
.cv
.winfo_width()
798 if width
<= 1: # the window isn't managed by a geometry manager
799 width
= self
.cv
['width']
800 height
= self
.cv
.winfo_height()
801 if height
<= 1: # the window isn't managed by a geometry manager
802 height
= self
.cv
['height']
806 ##############################################################################
807 ### End of Tkinter - interface ###
808 ##############################################################################
811 class Terminator (Exception):
812 """Will be raised in TurtleScreen.update, if _RUNNING becomes False.
814 Thus stops execution of turtle graphics script. Main purpose: use in
815 in the Demo-Viewer turtle.Demo.py.
820 class TurtleGraphicsError(Exception):
821 """Some TurtleGraphics Error
826 """Data structure modeling shapes.
828 attribute _type is one of "polygon", "image", "compound"
829 attribute _data is - depending on _type a poygon-tuple,
830 an image or a list constructed using the addcomponent method.
832 def __init__(self
, type_
, data
=None):
834 if type_
== "polygon":
835 if isinstance(data
, list):
837 elif type_
== "image":
838 if isinstance(data
, str):
839 if data
.lower().endswith(".gif") and isfile(data
):
840 data
= TurtleScreen
._image
(data
)
841 # else data assumed to be Photoimage
842 elif type_
== "compound":
845 raise TurtleGraphicsError("There is no shape type %s" % type_
)
848 def addcomponent(self
, poly
, fill
, outline
=None):
849 """Add component to a shape of type compound.
851 Arguments: poly is a polygon, i. e. a tuple of number pairs.
852 fill is the fillcolor of the component,
853 outline is the outline color of the component.
855 call (for a Shapeobject namend s):
856 -- s.addcomponent(((0,0), (10,10), (-10,10)), "red", "blue")
859 >>> poly = ((0,0),(10,-5),(0,10),(-10,-5))
860 >>> s = Shape("compound")
861 >>> s.addcomponent(poly, "red", "blue")
862 ### .. add more components and then use register_shape()
864 if self
._type
!= "compound":
865 raise TurtleGraphicsError("Cannot add component to %s Shape"
869 self
._data
.append([poly
, fill
, outline
])
872 class Tbuffer(object):
873 """Ring buffer used as undobuffer for RawTurtle objects."""
874 def __init__(self
, bufsize
=10):
875 self
.bufsize
= bufsize
876 self
.buffer = [[None]] * bufsize
878 self
.cumulate
= False
879 def reset(self
, bufsize
=None):
881 for i
in range(self
.bufsize
):
882 self
.buffer[i
] = [None]
884 self
.bufsize
= bufsize
885 self
.buffer = [[None]] * bufsize
887 def push(self
, item
):
889 if not self
.cumulate
:
890 self
.ptr
= (self
.ptr
+ 1) % self
.bufsize
891 self
.buffer[self
.ptr
] = item
893 self
.buffer[self
.ptr
].append(item
)
896 item
= self
.buffer[self
.ptr
]
900 self
.buffer[self
.ptr
] = [None]
901 self
.ptr
= (self
.ptr
- 1) % self
.bufsize
903 def nr_of_items(self
):
904 return self
.bufsize
- self
.buffer.count([None])
906 return str(self
.buffer) + " " + str(self
.ptr
)
910 class TurtleScreen(TurtleScreenBase
):
911 """Provides screen oriented methods like setbg etc.
913 Only relies upon the methods of TurtleScreenBase and NOT
914 upon components of the underlying graphics toolkit -
915 which is Tkinter in this case.
917 # _STANDARD_DELAY = 5
920 def __init__(self
, cv
, mode
=_CFG
["mode"],
921 colormode
=_CFG
["colormode"], delay
=_CFG
["delay"]):
923 "arrow" : Shape("polygon", ((-10,0), (10,0), (0,10))),
924 "turtle" : Shape("polygon", ((0,16), (-2,14), (-1,10), (-4,7),
925 (-7,9), (-9,8), (-6,5), (-7,1), (-5,-3), (-8,-6),
926 (-6,-8), (-4,-5), (0,-7), (4,-5), (6,-8), (8,-6),
927 (5,-3), (7,1), (6,5), (9,8), (7,9), (4,7), (1,10),
929 "circle" : Shape("polygon", ((10,0), (9.51,3.09), (8.09,5.88),
930 (5.88,8.09), (3.09,9.51), (0,10), (-3.09,9.51),
931 (-5.88,8.09), (-8.09,5.88), (-9.51,3.09), (-10,0),
932 (-9.51,-3.09), (-8.09,-5.88), (-5.88,-8.09),
933 (-3.09,-9.51), (-0.00,-10.00), (3.09,-9.51),
934 (5.88,-8.09), (8.09,-5.88), (9.51,-3.09))),
935 "square" : Shape("polygon", ((10,-10), (10,10), (-10,10),
937 "triangle" : Shape("polygon", ((10,-5.77), (0,11.55),
939 "classic": Shape("polygon", ((0,0),(-5,-9),(0,-7),(5,-9))),
940 "blank" : Shape("image", self
._blankimage
())
943 self
._bgpics
= {"nopic" : ""}
945 TurtleScreenBase
.__init
__(self
, cv
)
947 self
._delayvalue
= delay
948 self
._colormode
= _CFG
["colormode"]
953 """Delete all drawings and all turtles from the TurtleScreen.
955 Reset empty TurtleScreen to its initial state: white background,
956 no backgroundimage, no eventbindings and tracing on.
960 Example (for a TurtleScreen instance named screen):
963 Note: this method is not available as function.
965 self
._delayvalue
= _CFG
["delay"]
966 self
._colormode
= _CFG
["colormode"]
968 self
._bgpic
= self
._createimage
("")
969 self
._bgpicname
= "nopic"
971 self
._updatecounter
= 0
973 self
.bgcolor("white")
975 self
.onclick(None, btn
)
976 for key
in self
._keys
[:]:
977 self
.onkey(None, key
)
980 def mode(self
, mode
=None):
981 """Set turtle-mode ('standard', 'logo' or 'world') and perform reset.
984 mode -- on of the strings 'standard', 'logo' or 'world'
986 Mode 'standard' is compatible with turtle.py.
987 Mode 'logo' is compatible with most Logo-Turtle-Graphics.
988 Mode 'world' uses userdefined 'worldcoordinates'. *Attention*: in
989 this mode angles appear distorted if x/y unit-ratio doesn't equal 1.
990 If mode is not given, return the current mode.
992 Mode Initial turtle heading positive angles
993 ------------|-------------------------|-------------------
994 'standard' to the right (east) counterclockwise
995 'logo' upward (north) clockwise
998 >>> mode('logo') # resets turtle heading to north
1005 if mode
not in ["standard", "logo", "world"]:
1006 raise TurtleGraphicsError("No turtle-graphics-mode %s" % mode
)
1008 if mode
in ["standard", "logo"]:
1009 self
._setscrollregion
(-self
.canvwidth
//2, -self
.canvheight
//2,
1010 self
.canvwidth
//2, self
.canvheight
//2)
1011 self
.xscale
= self
.yscale
= 1.0
1014 def setworldcoordinates(self
, llx
, lly
, urx
, ury
):
1015 """Set up a user defined coordinate-system.
1018 llx -- a number, x-coordinate of lower left corner of canvas
1019 lly -- a number, y-coordinate of lower left corner of canvas
1020 urx -- a number, x-coordinate of upper right corner of canvas
1021 ury -- a number, y-coordinate of upper right corner of canvas
1023 Set up user coodinat-system and switch to mode 'world' if necessary.
1024 This performs a screen.reset. If mode 'world' is already active,
1025 all drawings are redrawn according to the new coordinates.
1027 But ATTENTION: in user-defined coordinatesystems angles may appear
1028 distorted. (see Screen.mode())
1030 Example (for a TurtleScreen instance named screen):
1031 >>> screen.setworldcoordinates(-10,-0.5,50,1.5)
1032 >>> for _ in range(36):
1036 if self
.mode() != "world":
1038 xspan
= float(urx
- llx
)
1039 yspan
= float(ury
- lly
)
1040 wx
, wy
= self
._window
_size
()
1041 self
.screensize(wx
-20, wy
-20)
1042 oldxscale
, oldyscale
= self
.xscale
, self
.yscale
1043 self
.xscale
= self
.canvwidth
/ xspan
1044 self
.yscale
= self
.canvheight
/ yspan
1045 srx1
= llx
* self
.xscale
1046 sry1
= -ury
* self
.yscale
1047 srx2
= self
.canvwidth
+ srx1
1048 sry2
= self
.canvheight
+ sry1
1049 self
._setscrollregion
(srx1
, sry1
, srx2
, sry2
)
1050 self
._rescale
(self
.xscale
/oldxscale
, self
.yscale
/oldyscale
)
1053 def register_shape(self
, name
, shape
=None):
1054 """Adds a turtle shape to TurtleScreen's shapelist.
1057 (1) name is the name of a gif-file and shape is None.
1058 Installs the corresponding image shape.
1059 !! Image-shapes DO NOT rotate when turning the turtle,
1060 !! so they do not display the heading of the turtle!
1061 (2) name is an arbitrary string and shape is a tuple
1062 of pairs of coordinates. Installs the corresponding
1064 (3) name is an arbitrary string and shape is a
1065 (compound) Shape object. Installs the corresponding
1067 To use a shape, you have to issue the command shape(shapename).
1069 call: register_shape("turtle.gif")
1070 --or: register_shape("tri", ((0,0), (10,10), (-10,10)))
1072 Example (for a TurtleScreen instance named screen):
1073 >>> screen.register_shape("triangle", ((5,-3),(0,5),(-5,-3)))
1078 if name
.lower().endswith(".gif"):
1079 shape
= Shape("image", self
._image
(name
))
1081 raise TurtleGraphicsError("Bad arguments for register_shape.\n"
1082 + "Use help(register_shape)" )
1083 elif isinstance(shape
, tuple):
1084 shape
= Shape("polygon", shape
)
1085 ## else shape assumed to be Shape-instance
1086 self
._shapes
[name
] = shape
1087 # print "shape added:" , self._shapes
1089 def _colorstr(self
, color
):
1090 """Return color string corresponding to args.
1092 Argument may be a string or a tuple of three
1093 numbers corresponding to actual colormode,
1094 i.e. in the range 0<=n<=colormode.
1096 If the argument doesn't represent a color,
1101 if isinstance(color
, str):
1102 if self
._iscolorstring
(color
) or color
== "":
1105 raise TurtleGraphicsError("bad color string: %s" % str(color
))
1109 raise TurtleGraphicsError("bad color arguments: %s" % str(color
))
1110 if self
._colormode
== 1.0:
1111 r
, g
, b
= [round(255.0*x
) for x
in (r
, g
, b
)]
1112 if not ((0 <= r
<= 255) and (0 <= g
<= 255) and (0 <= b
<= 255)):
1113 raise TurtleGraphicsError("bad color sequence: %s" % str(color
))
1114 return "#%02x%02x%02x" % (r
, g
, b
)
1116 def _color(self
, cstr
):
1117 if not cstr
.startswith("#"):
1120 cl
= [int(cstr
[i
:i
+2], 16) for i
in (1, 3, 5)]
1121 elif len(cstr
) == 4:
1122 cl
= [16*int(cstr
[h
], 16) for h
in cstr
[1:]]
1124 raise TurtleGraphicsError("bad colorstring: %s" % cstr
)
1125 return tuple([c
* self
._colormode
/255 for c
in cl
])
1127 def colormode(self
, cmode
=None):
1128 """Return the colormode or set it to 1.0 or 255.
1131 cmode -- one of the values 1.0 or 255
1133 r, g, b values of colortriples have to be in range 0..cmode.
1135 Example (for a TurtleScreen instance named screen):
1136 >>> screen.colormode()
1138 >>> screen.colormode(255)
1139 >>> turtle.pencolor(240,160,80)
1142 return self
._colormode
1144 self
._colormode
= float(cmode
)
1146 self
._colormode
= int(cmode
)
1149 """Reset all Turtles on the Screen to their initial state.
1153 Example (for a TurtleScreen instance named screen):
1156 for turtle
in self
._turtles
:
1157 turtle
._setmode
(self
._mode
)
1161 """Return the list of turtles on the screen.
1163 Example (for a TurtleScreen instance named screen):
1164 >>> screen.turtles()
1165 [<turtle.Turtle object at 0x00E11FB0>]
1167 return self
._turtles
1169 def bgcolor(self
, *args
):
1170 """Set or return backgroundcolor of the TurtleScreen.
1172 Arguments (if given): a color string or three numbers
1173 in the range 0..colormode or a 3-tuple of such numbers.
1175 Example (for a TurtleScreen instance named screen):
1176 >>> screen.bgcolor("orange")
1177 >>> screen.bgcolor()
1179 >>> screen.bgcolor(0.5,0,0.5)
1180 >>> screen.bgcolor()
1184 color
= self
._colorstr
(args
)
1187 color
= self
._bgcolor
(color
)
1188 if color
is not None:
1189 color
= self
._color
(color
)
1192 def tracer(self
, n
=None, delay
=None):
1193 """Turns turtle animation on/off and set delay for update drawings.
1196 n -- nonnegative integer
1197 delay -- nonnegative integer
1199 If n is given, only each n-th regular screen update is really performed.
1200 (Can be used to accelerate the drawing of complex graphics.)
1201 Second arguments sets delay value (see RawTurtle.delay())
1203 Example (for a TurtleScreen instance named screen):
1204 >>> screen.tracer(8, 25)
1206 >>> for i in range(200):
1212 return self
._tracing
1213 self
._tracing
= int(n
)
1214 self
._updatecounter
= 0
1215 if delay
is not None:
1216 self
._delayvalue
= int(delay
)
1220 def delay(self
, delay
=None):
1221 """ Return or set the drawing delay in milliseconds.
1224 delay -- positive integer
1226 Example (for a TurtleScreen instance named screen):
1227 >>> screen.delay(15)
1232 return self
._delayvalue
1233 self
._delayvalue
= int(delay
)
1235 def _incrementudc(self
):
1236 "Increment upadate counter."""
1237 if not TurtleScreen._RUNNING:
1238 TurtleScreen._RUNNNING = True
1240 if self._tracing > 0:
1241 self._updatecounter += 1
1242 self._updatecounter %= self._tracing
1245 """Perform a TurtleScreen update.
1247 tracing = self._tracing
1248 self._tracing = True
1249 for t in self.turtles():
1252 self._tracing = tracing
1255 def window_width(self):
1256 """ Return the width of the turtle window.
1258 Example (for a TurtleScreen instance named screen):
1259 >>> screen.window_width()
1262 return self._window_size()[0]
1264 def window_height(self):
1265 """ Return the height of the turtle window.
1267 Example (for a TurtleScreen instance named screen):
1268 >>> screen.window_height()
1271 return self._window_size()[1]
1273 def getcanvas(self):
1274 """Return the Canvas of this TurtleScreen.
1278 Example (for a Screen instance named screen):
1279 >>> cv = screen.getcanvas()
1281 <turtle.ScrolledCanvas instance at 0x010742D8>
1285 def getshapes(self):
1286 """Return a list of names of all currently available turtle shapes.
1290 Example (for a TurtleScreen instance named screen):
1291 >>> screen.getshapes()
1292 ['arrow', 'blank', 'circle', ... , 'turtle']
1294 return sorted(self._shapes.keys())
1296 def onclick(self, fun, btn=1, add=None):
1297 """Bind fun to mouse-click event on canvas.
1300 fun -- a function with two arguments, the coordinates of the
1301 clicked point on the canvas.
1302 num -- the number of the mouse-button, defaults to 1
1304 Example (for a TurtleScreen instance named screen
1305 and a Turtle instance named turtle):
1307 >>> screen.onclick(turtle.goto)
1309 ### Subsequently clicking into the TurtleScreen will
1310 ### make the turtle move to the clicked point.
1311 >>> screen.onclick(None)
1313 ### event-binding will be removed
1315 self._onscreenclick(fun, btn, add)
1317 def onkey(self, fun, key):
1318 """Bind fun to key-release event of key.
1321 fun -- a function with no arguments
1322 key -- a string: key (e.g. "a
") or key-symbol (e.g. "space
")
1324 In order to be able to register key-events, TurtleScreen
1325 must have focus. (See method listen.)
1327 Example (for a TurtleScreen instance named screen
1328 and a Turtle instance named turtle):
1335 >>> screen.onkey(f, "Up
")
1338 ### Subsequently the turtle can be moved by
1339 ### repeatedly pressing the up-arrow key,
1340 ### consequently drawing a hexagon
1343 if key in self._keys:
1344 self._keys.remove(key)
1345 elif key not in self._keys:
1346 self._keys.append(key)
1347 self._onkey(fun, key)
1349 def listen(self, xdummy=None, ydummy=None):
1350 """Set focus on TurtleScreen (in order to collect key-events)
1353 Dummy arguments are provided in order
1354 to be able to pass listen to the onclick method.
1356 Example (for a TurtleScreen instance named screen):
1361 def ontimer(self, fun, t=0):
1362 """Install a timer, which calls fun after t milliseconds.
1365 fun -- a function with no arguments.
1368 Example (for a TurtleScreen instance named screen):
1375 screen.ontimer(f, 250)
1377 >>> f() ### makes the turtle marching around
1380 self._ontimer(fun, t)
1382 def bgpic(self, picname=None):
1383 """Set background image or return name of current backgroundimage.
1386 picname -- a string, name of a gif-file or "nopic
".
1388 If picname is a filename, set the corresponing image as background.
1389 If picname is "nopic
", delete backgroundimage, if present.
1390 If picname is None, return the filename of the current backgroundimage.
1392 Example (for a TurtleScreen instance named screen):
1395 >>> screen.bgpic("landscape
.gif
")
1400 return self._bgpicname
1401 if picname not in self._bgpics:
1402 self._bgpics[picname] = self._image(picname)
1403 self._setbgpic(self._bgpic, self._bgpics[picname])
1404 self._bgpicname = picname
1406 def screensize(self, canvwidth=None, canvheight=None, bg=None):
1407 """Resize the canvas the turtles are drawing on.
1410 canvwidth -- positive integer, new width of canvas in pixels
1411 canvheight -- positive integer, new height of canvas in pixels
1412 bg -- colorstring or color-tupel, new backgroundcolor
1413 If no arguments are given, return current (canvaswidth, canvasheight)
1415 Do not alter the drawing window. To observe hidden parts of
1416 the canvas use the scrollbars. (Can make visible those parts
1417 of a drawing, which were outside the canvas before!)
1419 Example (for a Turtle instance named turtle):
1420 >>> turtle.screensize(2000,1500)
1421 ### e. g. to search for an erroneously escaped turtle ;-)
1423 return self._resize(canvwidth, canvheight, bg)
1425 onscreenclick = onclick
1428 addshape = register_shape
1430 class TNavigator(object):
1431 """Navigation part of the RawTurtle.
1432 Implements methods for turtle movement.
1434 START_ORIENTATION = {
1435 "standard
": Vec2D(1.0, 0.0),
1436 "world
" : Vec2D(1.0, 0.0),
1437 "logo
" : Vec2D(0.0, 1.0) }
1438 DEFAULT_MODE = "standard
"
1439 DEFAULT_ANGLEOFFSET = 0
1440 DEFAULT_ANGLEORIENT = 1
1442 def __init__(self, mode=DEFAULT_MODE):
1443 self._angleOffset = self.DEFAULT_ANGLEOFFSET
1444 self._angleOrient = self.DEFAULT_ANGLEORIENT
1446 self.undobuffer = None
1450 TNavigator.reset(self)
1453 """reset turtle to its initial values
1455 Will be overwritten by parent class
1457 self._position = Vec2D(0.0, 0.0)
1458 self._orient = TNavigator.START_ORIENTATION[self._mode]
1460 def _setmode(self, mode=None):
1461 """Set turtle-mode to 'standard', 'world' or 'logo'.
1465 if mode not in ["standard
", "logo
", "world
"]:
1468 if mode in ["standard
", "world
"]:
1469 self._angleOffset = 0
1470 self._angleOrient = 1
1471 else: # mode == "logo
":
1472 self._angleOffset = self._fullcircle/4.
1473 self._angleOrient = -1
1475 def _setDegreesPerAU(self, fullcircle):
1476 """Helper function for degrees() and radians()"""
1477 self._fullcircle = fullcircle
1478 self._degreesPerAU = 360/fullcircle
1479 if self._mode == "standard
":
1480 self._angleOffset = 0
1482 self._angleOffset = fullcircle/4.
1484 def degrees(self, fullcircle=360.0):
1485 """ Set angle measurement units to degrees.
1488 fullcircle - a number
1490 Set angle measurement units, i. e. set number
1491 of 'degrees' for a full circle. Dafault value is
1494 Example (for a Turtle instance named turtle):
1496 >>> turtle.heading()
1498 >>> turtle.degrees(400.0) # angle measurement in gon
1499 >>> turtle.heading()
1503 self._setDegreesPerAU(fullcircle)
1506 """ Set the angle measurement units to radians.
1510 Example (for a Turtle instance named turtle):
1511 >>> turtle.heading()
1513 >>> turtle.radians()
1514 >>> turtle.heading()
1517 self._setDegreesPerAU(2*math.pi)
1519 def _go(self, distance):
1520 """move turtle forward by specified distance"""
1521 ende = self._position + self._orient * distance
1524 def _rotate(self, angle):
1525 """Turn turtle counterclockwise by specified angle if angle > 0."""
1526 angle *= self._degreesPerAU
1527 self._orient = self._orient.rotate(angle)
1529 def _goto(self, end):
1530 """move turtle to position end."""
1531 self._position = end
1533 def forward(self, distance):
1534 """Move the turtle forward by the specified distance.
1536 Aliases: forward | fd
1539 distance -- a number (integer or float)
1541 Move the turtle forward by the specified distance, in the direction
1542 the turtle is headed.
1544 Example (for a Turtle instance named turtle):
1545 >>> turtle.position()
1547 >>> turtle.forward(25)
1548 >>> turtle.position()
1550 >>> turtle.forward(-75)
1551 >>> turtle.position()
1556 def back(self, distance):
1557 """Move the turtle backward by distance.
1559 Aliases: back | backward | bk
1562 distance -- a number
1564 Move the turtle backward by distance ,opposite to the direction the
1565 turtle is headed. Do not change the turtle's heading.
1567 Example (for a Turtle instance named turtle):
1568 >>> turtle.position()
1570 >>> turtle.backward(30)
1571 >>> turtle.position()
1576 def right(self, angle):
1577 """Turn turtle right by angle units.
1582 angle -- a number (integer or float)
1584 Turn turtle right by angle units. (Units are by default degrees,
1585 but can be set via the degrees() and radians() functions.)
1586 Angle orientation depends on mode. (See this.)
1588 Example (for a Turtle instance named turtle):
1589 >>> turtle.heading()
1591 >>> turtle.right(45)
1592 >>> turtle.heading()
1595 self._rotate(-angle)
1597 def left(self, angle):
1598 """Turn turtle left by angle units.
1603 angle -- a number (integer or float)
1605 Turn turtle left by angle units. (Units are by default degrees,
1606 but can be set via the degrees() and radians() functions.)
1607 Angle orientation depends on mode. (See this.)
1609 Example (for a Turtle instance named turtle):
1610 >>> turtle.heading()
1613 >>> turtle.heading()
1619 """Return the turtle's current location (x,y), as a Vec2D-vector.
1621 Aliases: pos | position
1625 Example (for a Turtle instance named turtle):
1629 return self._position
1632 """ Return the turtle's x coordinate.
1636 Example (for a Turtle instance named turtle):
1639 >>> turtle.forward(100)
1640 >>> print turtle.xcor()
1643 return self._position[0]
1646 """ Return the turtle's y coordinate
1650 Example (for a Turtle instance named turtle):
1653 >>> turtle.forward(100)
1654 >>> print turtle.ycor()
1657 return self._position[1]
1660 def goto(self, x, y=None):
1661 """Move turtle to an absolute position.
1663 Aliases: setpos | setposition | goto:
1666 x -- a number or a pair/vector of numbers
1669 call: goto(x, y) # two coordinates
1670 --or: goto((x, y)) # a pair (tuple) of coordinates
1671 --or: goto(vec) # e.g. as returned by pos()
1673 Move turtle to an absolute position. If the pen is down,
1674 a line will be drawn. The turtle's orientation does not change.
1676 Example (for a Turtle instance named turtle):
1677 >>> tp = turtle.pos()
1680 >>> turtle.setpos(60,30)
1683 >>> turtle.setpos((20,80))
1686 >>> turtle.setpos(tp)
1691 self._goto(Vec2D(*x))
1693 self._goto(Vec2D(x, y))
1696 """Move turtle to the origin - coordinates (0,0).
1700 Move turtle to the origin - coordinates (0,0) and set its
1701 heading to its start-orientation (which depends on mode).
1703 Example (for a Turtle instance named turtle):
1710 """Set the turtle's first coordinate to x
1713 x -- a number (integer or float)
1715 Set the turtle's first coordinate to x, leave second coordinate
1718 Example (for a Turtle instance named turtle):
1719 >>> turtle.position()
1722 >>> turtle.position()
1725 self._goto(Vec2D(x, self._position[1]))
1728 """Set the turtle's second coordinate to y
1731 y -- a number (integer or float)
1733 Set the turtle's first coordinate to x, second coordinate remains
1736 Example (for a Turtle instance named turtle):
1737 >>> turtle.position()
1739 >>> turtle.sety(-10)
1740 >>> turtle.position()
1743 self._goto(Vec2D(self._position[0], y))
1745 def distance(self, x, y=None):
1746 """Return the distance from the turtle to (x,y) in turtle step units.
1749 x -- a number or a pair/vector of numbers or a turtle instance
1750 y -- a number None None
1752 call: distance(x, y) # two coordinates
1753 --or: distance((x, y)) # a pair (tuple) of coordinates
1754 --or: distance(vec) # e.g. as returned by pos()
1755 --or: distance(mypen) # where mypen is another turtle
1757 Example (for a Turtle instance named turtle):
1760 >>> turtle.distance(30,40)
1764 >>> turtle.distance(pen)
1769 if isinstance(x, Vec2D):
1771 elif isinstance(x, tuple):
1773 elif isinstance(x, TNavigator):
1775 return abs(pos - self._position)
1777 def towards(self, x, y=None):
1778 """Return the angle of the line from the turtle's position to (x, y).
1781 x -- a number or a pair/vector of numbers or a turtle instance
1782 y -- a number None None
1784 call: distance(x, y) # two coordinates
1785 --or: distance((x, y)) # a pair (tuple) of coordinates
1786 --or: distance(vec) # e.g. as returned by pos()
1787 --or: distance(mypen) # where mypen is another turtle
1789 Return the angle, between the line from turtle-position to position
1790 specified by x, y and the turtle's start orientation. (Depends on
1791 modes - "standard
" or "logo
")
1793 Example (for a Turtle instance named turtle):
1796 >>> turtle.towards(0,0)
1801 if isinstance(x, Vec2D):
1803 elif isinstance(x, tuple):
1805 elif isinstance(x, TNavigator):
1807 x, y = pos - self._position
1808 result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0
1809 result /= self._degreesPerAU
1810 return (self._angleOffset + self._angleOrient*result) % self._fullcircle
1813 """ Return the turtle's current heading.
1817 Example (for a Turtle instance named turtle):
1819 >>> turtle.heading()
1823 result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0
1824 result /= self._degreesPerAU
1825 return (self._angleOffset + self._angleOrient*result) % self._fullcircle
1827 def setheading(self, to_angle):
1828 """Set the orientation of the turtle to to_angle.
1830 Aliases: setheading | seth
1833 to_angle -- a number (integer or float)
1835 Set the orientation of the turtle to to_angle.
1836 Here are some common directions in degrees:
1838 standard - mode: logo-mode:
1839 -------------------|--------------------
1841 90 - north 90 - east
1842 180 - west 180 - south
1843 270 - south 270 - west
1845 Example (for a Turtle instance named turtle):
1846 >>> turtle.setheading(90)
1847 >>> turtle.heading()
1850 angle = (to_angle - self.heading())*self._angleOrient
1851 full = self._fullcircle
1852 angle = (angle+full/2.)%full - full/2.
1855 def circle(self, radius, extent = None, steps = None):
1856 """ Draw a circle with given radius.
1860 extent (optional) -- a number
1861 steps (optional) -- an integer
1863 Draw a circle with given radius. The center is radius units left
1864 of the turtle; extent - an angle - determines which part of the
1865 circle is drawn. If extent is not given, draw the entire circle.
1866 If extent is not a full circle, one endpoint of the arc is the
1867 current pen position. Draw the arc in counterclockwise direction
1868 if radius is positive, otherwise in clockwise direction. Finally
1869 the direction of the turtle is changed by the amount of extent.
1871 As the circle is approximated by an inscribed regular polygon,
1872 steps determines the number of steps to use. If not given,
1873 it will be calculated automatically. Maybe used to draw regular
1876 call: circle(radius) # full circle
1877 --or: circle(radius, extent) # arc
1878 --or: circle(radius, extent, steps)
1879 --or: circle(radius, steps=6) # 6-sided polygon
1881 Example (for a Turtle instance named turtle):
1882 >>> turtle.circle(50)
1883 >>> turtle.circle(120, 180) # semicircle
1886 self.undobuffer.push(["seq
"])
1887 self.undobuffer.cumulate = True
1888 speed = self.speed()
1890 extent = self._fullcircle
1892 frac = abs(extent)/self._fullcircle
1893 steps = 1+int(min(11+abs(radius)/6.0, 59.0)*frac)
1894 w = 1.0 * extent / steps
1896 l = 2.0 * radius * math.sin(w2*math.pi/180.0*self._degreesPerAU)
1898 l, w, w2 = -l, -w, -w2
1906 for i in range(steps):
1916 self.undobuffer.cumulate = False
1918 ## three dummy methods to be implemented by child class:
1920 def speed(self, s=0):
1921 """dummy method - to be overwritten by child class"""
1922 def tracer(self, a=None, b=None):
1923 """dummy method - to be overwritten by child class"""
1924 def _delay(self, n=None):
1925 """dummy method - to be overwritten by child class"""
1939 """Drawing part of the RawTurtle.
1940 Implements drawing properties.
1942 def __init__(self, resizemode=_CFG["resizemode
"]):
1943 self._resizemode = resizemode # or "user
" or "noresize
"
1944 self.undobuffer = None
1947 def _reset(self, pencolor=_CFG["pencolor
"],
1948 fillcolor=_CFG["fillcolor
"]):
1951 self._pencolor = pencolor
1952 self._fillcolor = fillcolor
1953 self._drawing = True
1955 self._stretchfactor = (1, 1)
1957 self._outlinewidth = 1
1958 ### self.screen = None # to override by child class
1960 def resizemode(self, rmode=None):
1961 """Set resizemode to one of the values: "auto
", "user
", "noresize
".
1963 (Optional) Argument:
1964 rmode -- one of the strings "auto
", "user
", "noresize
"
1966 Different resizemodes have the following effects:
1967 - "auto
" adapts the appearance of the turtle
1968 corresponding to the value of pensize.
1969 - "user
" adapts the appearance of the turtle according to the
1970 values of stretchfactor and outlinewidth (outline),
1971 which are set by shapesize()
1972 - "noresize
" no adaption of the turtle's appearance takes place.
1973 If no argument is given, return current resizemode.
1974 resizemode("user
") is called by a call of shapesize with arguments.
1977 Examples (for a Turtle instance named turtle):
1978 >>> turtle.resizemode("noresize
")
1979 >>> turtle.resizemode()
1983 return self._resizemode
1984 rmode = rmode.lower()
1985 if rmode in ["auto
", "user
", "noresize
"]:
1986 self.pen(resizemode=rmode)
1988 def pensize(self, width=None):
1989 """Set or return the line thickness.
1991 Aliases: pensize | width
1994 width -- positive number
1996 Set the line thickness to width or return it. If resizemode is set
1997 to "auto
" and turtleshape is a polygon, that polygon is drawn with
1998 the same line thickness. If no argument is given, current pensize
2001 Example (for a Turtle instance named turtle):
2002 >>> turtle.pensize()
2004 turtle.pensize(10) # from here on lines of width 10 are drawn
2007 return self._pensize
2008 self.pen(pensize=width)
2012 """Pull the pen up -- no drawing when moving.
2014 Aliases: penup | pu | up
2018 Example (for a Turtle instance named turtle):
2021 if not self._drawing:
2023 self.pen(pendown=False)
2026 """Pull the pen down -- drawing when moving.
2028 Aliases: pendown | pd | down
2032 Example (for a Turtle instance named turtle):
2033 >>> turtle.pendown()
2037 self.pen(pendown=True)
2040 """Return True if pen is down, False if it's up.
2044 Example (for a Turtle instance named turtle):
2048 >>> turtle.pendown()
2052 return self._drawing
2054 def speed(self, speed=None):
2055 """ Return or set the turtle's speed.
2058 speed -- an integer in the range 0..10 or a speedstring (see below)
2060 Set the turtle's speed to an integer value in the range 0 .. 10.
2061 If no argument is given: return current speed.
2063 If input is a number greater than 10 or smaller than 0.5,
2065 Speedstrings are mapped to speedvalues in the following way:
2071 speeds from 1 to 10 enforce increasingly faster animation of
2072 line drawing and turtle turning.
2075 speed = 0 : *no* animation takes place. forward/back makes turtle jump
2076 and likewise left/right make the turtle turn instantly.
2078 Example (for a Turtle instance named turtle):
2081 speeds = {'fastest':0, 'fast':10, 'normal':6, 'slow':3, 'slowest':1 }
2085 speed = speeds[speed]
2086 elif 0.5 < speed < 10.5:
2087 speed = int(round(speed))
2090 self.pen(speed=speed)
2092 def color(self, *args):
2093 """Return or set the pencolor and fillcolor.
2096 Several input formats are allowed.
2097 They use 0, 1, 2, or 3 arguments as follows:
2100 Return the current pencolor and the current fillcolor
2101 as a pair of color specification strings as are returned
2102 by pencolor and fillcolor.
2103 color(colorstring), color((r,g,b)), color(r,g,b)
2104 inputs as in pencolor, set both, fillcolor and pencolor,
2106 color(colorstring1, colorstring2),
2107 color((r1,g1,b1), (r2,g2,b2))
2108 equivalent to pencolor(colorstring1) and fillcolor(colorstring2)
2109 and analogously, if the other input format is used.
2111 If turtleshape is a polygon, outline and interior of that polygon
2112 is drawn with the newly set colors.
2113 For mor info see: pencolor, fillcolor
2115 Example (for a Turtle instance named turtle):
2116 >>> turtle.color('red', 'green')
2120 >>> color((40, 80, 120), (160, 200, 240))
2122 ('#285078', '#a0c8f0')
2127 pcolor = fcolor = args[0]
2129 pcolor, fcolor = args
2131 pcolor = fcolor = args
2132 pcolor = self._colorstr(pcolor)
2133 fcolor = self._colorstr(fcolor)
2134 self.pen(pencolor=pcolor, fillcolor=fcolor)
2136 return self._color(self._pencolor), self._color(self._fillcolor)
2138 def pencolor(self, *args):
2139 """ Return or set the pencolor.
2142 Four input formats are allowed:
2144 Return the current pencolor as color specification string,
2145 possibly in hex-number format (see example).
2146 May be used as input to another color/pencolor/fillcolor call.
2147 - pencolor(colorstring)
2148 s is a Tk color specification string, such as "red
" or "yellow
"
2149 - pencolor((r, g, b))
2150 *a tuple* of r, g, and b, which represent, an RGB color,
2151 and each of r, g, and b are in the range 0..colormode,
2152 where colormode is either 1.0 or 255
2154 r, g, and b represent an RGB color, and each of r, g, and b
2155 are in the range 0..colormode
2157 If turtleshape is a polygon, the outline of that polygon is drawn
2158 with the newly set pencolor.
2160 Example (for a Turtle instance named turtle):
2161 >>> turtle.pencolor('brown')
2162 >>> tup = (0.2, 0.8, 0.55)
2163 >>> turtle.pencolor(tup)
2164 >>> turtle.pencolor()
2168 color = self._colorstr(args)
2169 if color == self._pencolor:
2171 self.pen(pencolor=color)
2173 return self._color(self._pencolor)
2175 def fillcolor(self, *args):
2176 """ Return or set the fillcolor.
2179 Four input formats are allowed:
2181 Return the current fillcolor as color specification string,
2182 possibly in hex-number format (see example).
2183 May be used as input to another color/pencolor/fillcolor call.
2184 - fillcolor(colorstring)
2185 s is a Tk color specification string, such as "red
" or "yellow
"
2186 - fillcolor((r, g, b))
2187 *a tuple* of r, g, and b, which represent, an RGB color,
2188 and each of r, g, and b are in the range 0..colormode,
2189 where colormode is either 1.0 or 255
2190 - fillcolor(r, g, b)
2191 r, g, and b represent an RGB color, and each of r, g, and b
2192 are in the range 0..colormode
2194 If turtleshape is a polygon, the interior of that polygon is drawn
2195 with the newly set fillcolor.
2197 Example (for a Turtle instance named turtle):
2198 >>> turtle.fillcolor('violet')
2199 >>> col = turtle.pencolor()
2200 >>> turtle.fillcolor(col)
2201 >>> turtle.fillcolor(0, .5, 0)
2204 color = self._colorstr(args)
2205 if color == self._fillcolor:
2207 self.pen(fillcolor=color)
2209 return self._color(self._fillcolor)
2211 def showturtle(self):
2212 """Makes the turtle visible.
2214 Aliases: showturtle | st
2218 Example (for a Turtle instance named turtle):
2219 >>> turtle.hideturtle()
2220 >>> turtle.showturtle()
2222 self.pen(shown=True)
2224 def hideturtle(self):
2225 """Makes the turtle invisible.
2227 Aliases: hideturtle | ht
2231 It's a good idea to do this while you're in the
2232 middle of a complicated drawing, because hiding
2233 the turtle speeds up the drawing observably.
2235 Example (for a Turtle instance named turtle):
2236 >>> turtle.hideturtle()
2238 self.pen(shown=False)
2240 def isvisible(self):
2241 """Return True if the Turtle is shown, False if it's hidden.
2245 Example (for a Turtle instance named turtle):
2246 >>> turtle.hideturtle()
2247 >>> print turtle.isvisible():
2252 def pen(self, pen=None, **pendict):
2253 """Return or set the pen's attributes.
2256 pen -- a dictionary with some or all of the below listed keys.
2257 **pendict -- one or more keyword-arguments with the below
2258 listed keys as keywords.
2260 Return or set the pen's attributes in a 'pen-dictionary'
2261 with the following key/value pairs:
2262 "shown
" : True/False
2263 "pendown
" : True/False
2264 "pencolor
" : color-string or color-tuple
2265 "fillcolor
" : color-string or color-tuple
2266 "pensize
" : positive number
2267 "speed
" : number in range 0..10
2268 "resizemode
" : "auto
" or "user
" or "noresize
"
2269 "stretchfactor
": (positive number, positive number)
2270 "outline
" : positive number
2273 This dictionary can be used as argument for a subsequent
2274 pen()-call to restore the former pen-state. Moreover one
2275 or more of these attributes can be provided as keyword-arguments.
2276 This can be used to set several pen attributes in one statement.
2279 Examples (for a Turtle instance named turtle):
2280 >>> turtle.pen(fillcolor="black
", pencolor="red
", pensize=10)
2282 {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1,
2283 'pencolor': 'red', 'pendown': True, 'fillcolor': 'black',
2284 'stretchfactor': (1,1), 'speed': 3}
2285 >>> penstate=turtle.pen()
2286 >>> turtle.color("yellow
","")
2289 {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1,
2290 'pencolor': 'yellow', 'pendown': False, 'fillcolor': '',
2291 'stretchfactor': (1,1), 'speed': 3}
2292 >>> p.pen(penstate, fillcolor="green
")
2294 {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1,
2295 'pencolor': 'red', 'pendown': True, 'fillcolor': 'green',
2296 'stretchfactor': (1,1), 'speed': 3}
2298 _pd = {"shown
" : self._shown,
2299 "pendown
" : self._drawing,
2300 "pencolor
" : self._pencolor,
2301 "fillcolor
" : self._fillcolor,
2302 "pensize
" : self._pensize,
2303 "speed
" : self._speed,
2304 "resizemode
" : self._resizemode,
2305 "stretchfactor
" : self._stretchfactor,
2306 "outline
" : self._outlinewidth,
2310 if not (pen or pendict):
2313 if isinstance(pen, dict):
2321 _p_buf[key] = _pd[key]
2324 self.undobuffer.push(("pen
", _p_buf))
2328 if self._drawing != p["pendown
"]:
2331 if isinstance(p["pencolor
"], tuple):
2332 p["pencolor
"] = self._colorstr((p["pencolor
"],))
2333 if self._pencolor != p["pencolor
"]:
2336 if self._pensize != p["pensize
"]:
2341 self._drawing = p["pendown
"]
2343 self._pencolor = p["pencolor
"]
2345 self._pensize = p["pensize
"]
2346 if "fillcolor
" in p:
2347 if isinstance(p["fillcolor
"], tuple):
2348 p["fillcolor
"] = self._colorstr((p["fillcolor
"],))
2349 self._fillcolor = p["fillcolor
"]
2351 self._speed = p["speed
"]
2352 if "resizemode
" in p:
2353 self._resizemode = p["resizemode
"]
2354 if "stretchfactor
" in p:
2355 sf = p["stretchfactor
"]
2356 if isinstance(sf, (int, float)):
2358 self._stretchfactor = sf
2360 self._outlinewidth = p["outline
"]
2362 self._shown = p["shown
"]
2364 self._tilt = p["tilt
"]
2367 ## three dummy methods to be implemented by child class:
2369 def _newLine(self, usePos = True):
2370 """dummy method - to be overwritten by child class"""
2371 def _update(self, count=True, forced=False):
2372 """dummy method - to be overwritten by child class"""
2373 def _color(self, args):
2374 """dummy method - to be overwritten by child class"""
2375 def _colorstr(self, args):
2376 """dummy method - to be overwritten by child class"""
2387 class _TurtleImage(object):
2388 """Helper class: Datatype to store Turtle attributes
2391 def __init__(self, screen, shapeIndex):
2392 self.screen = screen
2394 self._setshape(shapeIndex)
2396 def _setshape(self, shapeIndex):
2397 screen = self.screen # RawTurtle.screens[self.screenIndex]
2398 self.shapeIndex = shapeIndex
2399 if self._type == "polygon
" == screen._shapes[shapeIndex]._type:
2401 if self._type == "image
" == screen._shapes[shapeIndex]._type:
2403 if self._type in ["image
", "polygon
"]:
2404 screen._delete(self._item)
2405 elif self._type == "compound
":
2406 for item in self._item:
2407 screen._delete(item)
2408 self._type = screen._shapes[shapeIndex]._type
2409 if self._type == "polygon
":
2410 self._item = screen._createpoly()
2411 elif self._type == "image
":
2412 self._item = screen._createimage(screen._shapes["blank
"]._data)
2413 elif self._type == "compound
":
2414 self._item = [screen._createpoly() for item in
2415 screen._shapes[shapeIndex]._data]
2418 class RawTurtle(TPen, TNavigator):
2419 """Animation part of the RawTurtle.
2420 Puts RawTurtle upon a TurtleScreen and provides tools for
2425 def __init__(self, canvas=None,
2426 shape=_CFG["shape
"],
2427 undobuffersize=_CFG["undobuffersize
"],
2428 visible=_CFG["visible
"]):
2429 if isinstance(canvas, _Screen):
2430 self.screen = canvas
2431 elif isinstance(canvas, TurtleScreen):
2432 if canvas not in RawTurtle.screens:
2433 RawTurtle.screens.append(canvas)
2434 self.screen = canvas
2435 elif isinstance(canvas, (ScrolledCanvas, Canvas)):
2436 for screen in RawTurtle.screens:
2437 if screen.cv == canvas:
2438 self.screen = screen
2441 self.screen = TurtleScreen(canvas)
2442 RawTurtle.screens.append(self.screen)
2444 raise TurtleGraphicsError("bad cavas argument
%s" % canvas)
2446 screen = self.screen
2447 TNavigator.__init__(self, screen.mode())
2449 screen._turtles.append(self)
2450 self.drawingLineItem = screen._createline()
2451 self.turtle = _TurtleImage(screen, shape)
2453 self._creatingPoly = False
2454 self._fillitem = self._fillpath = None
2455 self._shown = visible
2456 self._hidden_from_screen = False
2457 self.currentLineItem = screen._createline()
2458 self.currentLine = [self._position]
2459 self.items = [self.currentLineItem]
2460 self.stampItems = []
2461 self._undobuffersize = undobuffersize
2462 self.undobuffer = Tbuffer(undobuffersize)
2466 """Delete the turtle's drawings and restore its default values.
2470 Delete the turtle's drawings from the screen, re-center the turtle
2471 and set variables to the default values.
2473 Example (for a Turtle instance named turtle):
2474 >>> turtle.position()
2476 >>> turtle.heading()
2479 >>> turtle.position()
2481 >>> turtle.heading()
2484 TNavigator.reset(self)
2490 def setundobuffer(self, size):
2491 """Set or disable undobuffer.
2494 size -- an integer or None
2496 If size is an integer an empty undobuffer of given size is installed.
2497 Size gives the maximum number of turtle-actions that can be undone
2498 by the undo() function.
2499 If size is None, no undobuffer is present.
2501 Example (for a Turtle instance named turtle):
2502 >>> turtle.setundobuffer(42)
2505 self.undobuffer = None
2507 self.undobuffer = Tbuffer(size)
2509 def undobufferentries(self):
2510 """Return count of entries in the undobuffer.
2514 Example (for a Turtle instance named turtle):
2515 >>> while undobufferentries():
2518 if self.undobuffer is None:
2520 return self.undobuffer.nr_of_items()
2523 """Delete all of pen's drawings"""
2524 self._fillitem = self._fillpath = None
2525 for item in self.items:
2526 self.screen._delete(item)
2527 self.currentLineItem = self.screen._createline()
2528 self.currentLine = []
2530 self.currentLine.append(self._position)
2531 self.items = [self.currentLineItem]
2533 self.setundobuffer(self._undobuffersize)
2537 """Delete the turtle's drawings from the screen. Do not move turtle.
2541 Delete the turtle's drawings from the screen. Do not move turtle.
2542 State and position of the turtle as well as drawings of other
2543 turtles are not affected.
2545 Examples (for a Turtle instance named turtle):
2551 def _update_data(self):
2552 self.screen._incrementudc()
2553 if self.screen._updatecounter != 0:
2555 if len(self.currentLine)>1:
2556 self.screen._drawline(self.currentLineItem, self.currentLine,
2557 self._pencolor, self._pensize)
2560 """Perform a Turtle-data update.
2562 screen = self.screen
2563 if screen._tracing == 0:
2565 elif screen._tracing == 1:
2568 screen._update() # TurtleScreenBase
2569 screen._delay(screen._delayvalue) # TurtleScreenBase
2572 if screen._updatecounter == 0:
2573 for t in screen.turtles():
2577 def tracer(self, flag=None, delay=None):
2578 """Turns turtle animation on/off and set delay for update drawings.
2581 n -- nonnegative integer
2582 delay -- nonnegative integer
2584 If n is given, only each n-th regular screen update is really performed.
2585 (Can be used to accelerate the drawing of complex graphics.)
2586 Second arguments sets delay value (see RawTurtle.delay())
2588 Example (for a Turtle instance named turtle):
2589 >>> turtle.tracer(8, 25)
2591 >>> for i in range(200):
2596 return self.screen.tracer(flag, delay)
2598 def _color(self, args):
2599 return self.screen._color(args)
2601 def _colorstr(self, args):
2602 return self.screen._colorstr(args)
2604 def _cc(self, args):
2605 """Convert colortriples to hexstrings.
2607 if isinstance(args, str):
2612 raise TurtleGraphicsError("bad color arguments
: %s" % str(args))
2613 if self.screen._colormode == 1.0:
2614 r, g, b = [round(255.0*x) for x in (r, g, b)]
2615 if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)):
2616 raise TurtleGraphicsError("bad color sequence
: %s" % str(args))
2617 return "#%02x%02x%02x" % (r, g, b)
2620 """Create and return a clone of the turtle.
2624 Create and return a clone of the turtle with same position, heading
2625 and turtle properties.
2627 Example (for a Turtle instance named mick):
2631 screen
= self
.screen
2632 self
._newLine
(self
._drawing
)
2634 turtle
= self
.turtle
2636 self
.turtle
= None # too make self deepcopy-able
2640 self
.screen
= screen
2641 self
.turtle
= turtle
2644 q
.turtle
= _TurtleImage(screen
, self
.turtle
.shapeIndex
)
2646 screen
._turtles
.append(q
)
2647 ttype
= screen
._shapes
[self
.turtle
.shapeIndex
]._type
2648 if ttype
== "polygon":
2649 q
.turtle
._item
= screen
._createpoly
()
2650 elif ttype
== "image":
2651 q
.turtle
._item
= screen
._createimage
(screen
._shapes
["blank"]._data
)
2652 elif ttype
== "compound":
2653 q
.turtle
._item
= [screen
._createpoly
() for item
in
2654 screen
._shapes
[self
.turtle
.shapeIndex
]._data
]
2655 q
.currentLineItem
= screen
._createline
()
2659 def shape(self
, name
=None):
2660 """Set turtle shape to shape with given name / return current shapename.
2663 name -- a string, which is a valid shapename
2665 Set turtle shape to shape with given name or, if name is not given,
2666 return name of current shape.
2667 Shape with name must exist in the TurtleScreen's shape dictionary.
2668 Initially there are the following polygon shapes:
2669 'arrow', 'turtle', 'circle', 'square', 'triangle', 'classic'.
2670 To learn about how to deal with shapes see Screen-method register_shape.
2672 Example (for a Turtle instance named turtle):
2675 >>> turtle.shape("turtle")
2680 return self
.turtle
.shapeIndex
2681 if not name
in self
.screen
.getshapes():
2682 raise TurtleGraphicsError("There is no shape named %s" % name
)
2683 self
.turtle
._setshape
(name
)
2686 def shapesize(self
, stretch_wid
=None, stretch_len
=None, outline
=None):
2687 """Set/return turtle's stretchfactors/outline. Set resizemode to "user".
2689 Optinonal arguments:
2690 stretch_wid : positive number
2691 stretch_len : positive number
2692 outline : positive number
2694 Return or set the pen's attributes x/y-stretchfactors and/or outline.
2695 Set resizemode to "user".
2696 If and only if resizemode is set to "user", the turtle will be displayed
2697 stretched according to its stretchfactors:
2698 stretch_wid is stretchfactor perpendicular to orientation
2699 stretch_len is stretchfactor in direction of turtles orientation.
2700 outline determines the width of the shapes's outline.
2702 Examples (for a Turtle instance named turtle):
2703 >>> turtle.resizemode("user")
2704 >>> turtle.shapesize(5, 5, 12)
2705 >>> turtle.shapesize(outline=8)
2707 if stretch_wid
is None and stretch_len
is None and outline
== None:
2708 stretch_wid
, stretch_len
= self
._stretchfactor
2709 return stretch_wid
, stretch_len
, self
._outlinewidth
2710 if stretch_wid
is not None:
2711 if stretch_len
is None:
2712 stretchfactor
= stretch_wid
, stretch_wid
2714 stretchfactor
= stretch_wid
, stretch_len
2715 elif stretch_len
is not None:
2716 stretchfactor
= self
._stretchfactor
[0], stretch_len
2718 stretchfactor
= self
._stretchfactor
2720 outline
= self
._outlinewidth
2721 self
.pen(resizemode
="user",
2722 stretchfactor
=stretchfactor
, outline
=outline
)
2724 def settiltangle(self
, angle
):
2725 """Rotate the turtleshape to point in the specified direction
2730 Rotate the turtleshape to point in the direction specified by angle,
2731 regardless of its current tilt-angle. DO NOT change the turtle's
2732 heading (direction of movement).
2735 Examples (for a Turtle instance named turtle):
2736 >>> turtle.shape("circle")
2737 >>> turtle.shapesize(5,2)
2738 >>> turtle.settiltangle(45)
2741 >>> turtle.settiltangle(-45)
2745 tilt
= -angle
* self
._degreesPerAU
* self
._angleOrient
2746 tilt
= (tilt
* math
.pi
/ 180.0) % (2*math
.pi
)
2747 self
.pen(resizemode
="user", tilt
=tilt
)
2749 def tiltangle(self
):
2750 """Return the current tilt-angle.
2754 Return the current tilt-angle, i. e. the angle between the
2755 orientation of the turtleshape and the heading of the turtle
2756 (its direction of movement).
2758 Examples (for a Turtle instance named turtle):
2759 >>> turtle.shape("circle")
2760 >>> turtle.shapesize(5,2)
2762 >>> turtle.tiltangle()
2765 tilt
= -self
._tilt
* (180.0/math
.pi
) * self
._angleOrient
2766 return (tilt
/ self
._degreesPerAU
) % self
._fullcircle
2768 def tilt(self
, angle
):
2769 """Rotate the turtleshape by angle.
2774 Rotate the turtleshape by angle from its current tilt-angle,
2775 but do NOT change the turtle's heading (direction of movement).
2777 Examples (for a Turtle instance named turtle):
2778 >>> turtle.shape("circle")
2779 >>> turtle.shapesize(5,2)
2785 self
.settiltangle(angle
+ self
.tiltangle())
2787 def _polytrafo(self
, poly
):
2788 """Computes transformed polygon shapes from a shape
2789 according to current position and heading.
2791 screen
= self
.screen
2792 p0
, p1
= self
._position
2793 e0
, e1
= self
._orient
2794 e
= Vec2D(e0
, e1
* screen
.yscale
/ screen
.xscale
)
2795 e0
, e1
= (1.0 / abs(e
)) * e
2796 return [(p0
+(e1
*x
+e0
*y
)/screen
.xscale
, p1
+(-e0
*x
+e1
*y
)/screen
.yscale
)
2799 def _drawturtle(self
):
2800 """Manages the correct rendering of the turtle with respect to
2801 its shape, resizemode, stretch and tilt etc."""
2802 screen
= self
.screen
2803 shape
= screen
._shapes
[self
.turtle
.shapeIndex
]
2805 titem
= self
.turtle
._item
2806 if self
._shown
and screen
._updatecounter
== 0 and screen
._tracing
> 0:
2807 self
._hidden
_from
_screen
= False
2808 tshape
= shape
._data
2809 if ttype
== "polygon":
2810 if self
._resizemode
== "noresize":
2814 if self
._resizemode
== "auto":
2815 lx
= ly
= max(1, self
._pensize
/5.0)
2818 elif self
._resizemode
== "user":
2819 lx
, ly
= self
._stretchfactor
2820 w
= self
._outlinewidth
2821 tiltangle
= self
._tilt
2822 shape
= [(lx
*x
, ly
*y
) for (x
, y
) in tshape
]
2823 t0
, t1
= math
.sin(tiltangle
), math
.cos(tiltangle
)
2824 shape
= [(t1
*x
+t0
*y
, -t0
*x
+t1
*y
) for (x
, y
) in shape
]
2825 shape
= self
._polytrafo
(shape
)
2826 fc
, oc
= self
._fillcolor
, self
._pencolor
2827 screen
._drawpoly
(titem
, shape
, fill
=fc
, outline
=oc
,
2829 elif ttype
== "image":
2830 screen
._drawimage
(titem
, self
._position
, tshape
)
2831 elif ttype
== "compound":
2832 lx
, ly
= self
._stretchfactor
2833 w
= self
._outlinewidth
2834 for item
, (poly
, fc
, oc
) in zip(titem
, tshape
):
2835 poly
= [(lx
*x
, ly
*y
) for (x
, y
) in poly
]
2836 poly
= self
._polytrafo
(poly
)
2837 screen
._drawpoly
(item
, poly
, fill
=self
._cc
(fc
),
2838 outline
=self
._cc
(oc
), width
=w
, top
=True)
2840 if self
._hidden
_from
_screen
:
2842 if ttype
== "polygon":
2843 screen
._drawpoly
(titem
, ((0, 0), (0, 0), (0, 0)), "", "")
2844 elif ttype
== "image":
2845 screen
._drawimage
(titem
, self
._position
,
2846 screen
._shapes
["blank"]._data
)
2847 elif ttype
== "compound":
2849 screen
._drawpoly
(item
, ((0, 0), (0, 0), (0, 0)), "", "")
2850 self
._hidden
_from
_screen
= True
2852 ############################## stamp stuff ###############################
2855 """Stamp a copy of the turtleshape onto the canvas and return its id.
2859 Stamp a copy of the turtle shape onto the canvas at the current
2860 turtle position. Return a stamp_id for that stamp, which can be
2861 used to delete it by calling clearstamp(stamp_id).
2863 Example (for a Turtle instance named turtle):
2864 >>> turtle.color("blue")
2869 screen
= self
.screen
2870 shape
= screen
._shapes
[self
.turtle
.shapeIndex
]
2872 tshape
= shape
._data
2873 if ttype
== "polygon":
2874 stitem
= screen
._createpoly
()
2875 if self
._resizemode
== "noresize":
2879 if self
._resizemode
== "auto":
2880 lx
= ly
= max(1, self
._pensize
/5.0)
2883 elif self
._resizemode
== "user":
2884 lx
, ly
= self
._stretchfactor
2885 w
= self
._outlinewidth
2886 tiltangle
= self
._tilt
2887 shape
= [(lx
*x
, ly
*y
) for (x
, y
) in tshape
]
2888 t0
, t1
= math
.sin(tiltangle
), math
.cos(tiltangle
)
2889 shape
= [(t1
*x
+t0
*y
, -t0
*x
+t1
*y
) for (x
, y
) in shape
]
2890 shape
= self
._polytrafo
(shape
)
2891 fc
, oc
= self
._fillcolor
, self
._pencolor
2892 screen
._drawpoly
(stitem
, shape
, fill
=fc
, outline
=oc
,
2894 elif ttype
== "image":
2895 stitem
= screen
._createimage
("")
2896 screen
._drawimage
(stitem
, self
._position
, tshape
)
2897 elif ttype
== "compound":
2899 for element
in tshape
:
2900 item
= screen
._createpoly
()
2902 stitem
= tuple(stitem
)
2903 lx
, ly
= self
._stretchfactor
2904 w
= self
._outlinewidth
2905 for item
, (poly
, fc
, oc
) in zip(stitem
, tshape
):
2906 poly
= [(lx
*x
, ly
*y
) for (x
, y
) in poly
]
2907 poly
= self
._polytrafo
(poly
)
2908 screen
._drawpoly
(item
, poly
, fill
=self
._cc
(fc
),
2909 outline
=self
._cc
(oc
), width
=w
, top
=True)
2910 self
.stampItems
.append(stitem
)
2911 self
.undobuffer
.push(("stamp", stitem
))
2914 def _clearstamp(self
, stampid
):
2915 """does the work for clearstamp() and clearstamps()
2917 if stampid
in self
.stampItems
:
2918 if isinstance(stampid
, tuple):
2919 for subitem
in stampid
:
2920 self
.screen
._delete
(subitem
)
2922 self
.screen
._delete
(stampid
)
2923 self
.stampItems
.remove(stampid
)
2924 # Delete stampitem from undobuffer if necessary
2925 # if clearstamp is called directly.
2926 item
= ("stamp", stampid
)
2927 buf
= self
.undobuffer
2928 if item
not in buf
.buffer:
2930 index
= buf
.buffer.index(item
)
2931 buf
.buffer.remove(item
)
2932 if index
<= buf
.ptr
:
2933 buf
.ptr
= (buf
.ptr
- 1) % buf
.bufsize
2934 buf
.buffer.insert((buf
.ptr
+1)%buf
.bufsize
, [None])
2936 def clearstamp(self
, stampid
):
2937 """Delete stamp with given stampid
2940 stampid - an integer, must be return value of previous stamp() call.
2942 Example (for a Turtle instance named turtle):
2943 >>> turtle.color("blue")
2944 >>> astamp = turtle.stamp()
2946 >>> turtle.clearstamp(astamp)
2948 self
._clearstamp
(stampid
)
2951 def clearstamps(self
, n
=None):
2952 """Delete all or first/last n of turtle's stamps.
2957 If n is None, delete all of pen's stamps,
2958 else if n > 0 delete first n stamps
2959 else if n < 0 delete last n stamps.
2961 Example (for a Turtle instance named turtle):
2962 >>> for i in range(8):
2963 turtle.stamp(); turtle.fd(30)
2965 >>> turtle.clearstamps(2)
2966 >>> turtle.clearstamps(-2)
2967 >>> turtle.clearstamps()
2970 toDelete
= self
.stampItems
[:]
2972 toDelete
= self
.stampItems
[:n
]
2974 toDelete
= self
.stampItems
[n
:]
2975 for item
in toDelete
:
2976 self
._clearstamp
(item
)
2979 def _goto(self
, end
):
2980 """Move the pen to the point end, thereby drawing a line
2981 if pen is down. All other methodes for turtle movement depend
2984 ## Version mit undo-stuff
2985 go_modes
= ( self
._drawing
,
2988 isinstance(self
._fillpath
, list))
2989 screen
= self
.screen
2990 undo_entry
= ("go", self
._position
, end
, go_modes
,
2991 (self
.currentLineItem
,
2992 self
.currentLine
[:],
2993 screen
._pointlist
(self
.currentLineItem
),
2997 self
.undobuffer
.push(undo_entry
)
2998 start
= self
._position
2999 if self
._speed
and screen
._tracing
== 1:
3001 diffsq
= (diff
[0]*screen
.xscale
)**2 + (diff
[1]*screen
.yscale
)**2
3002 nhops
= 1+int((diffsq
**0.5)/(3*(1.1**self
._speed
)*self
._speed
))
3003 delta
= diff
* (1.0/nhops
)
3004 for n
in range(1, nhops
):
3009 self
._position
= start
+ delta
* n
3011 screen
._drawline
(self
.drawingLineItem
,
3012 (start
, self
._position
),
3013 self
._pencolor
, self
._pensize
, top
)
3016 screen
._drawline
(self
.drawingLineItem
, ((0, 0), (0, 0)),
3017 fill
="", width
=self
._pensize
)
3018 # Turtle now at end,
3019 if self
._drawing
: # now update currentLine
3020 self
.currentLine
.append(end
)
3021 if isinstance(self
._fillpath
, list):
3022 self
._fillpath
.append(end
)
3023 ###### vererbung!!!!!!!!!!!!!!!!!!!!!!
3024 self
._position
= end
3025 if self
._creatingPoly
:
3026 self
._poly
.append(end
)
3027 if len(self
.currentLine
) > 42: # 42! answer to the ultimate question
3028 # of life, the universe and everything
3030 self
._update
() #count=True)
3032 def _undogoto(self
, entry
):
3033 """Reverse a _goto. Used for undo()
3035 old
, new
, go_modes
, coodata
= entry
3036 drawing
, pc
, ps
, filling
= go_modes
3037 cLI
, cL
, pl
, items
= coodata
3038 screen
= self
.screen
3039 if abs(self
._position
- new
) > 0.5:
3040 print "undogoto: HALLO-DA-STIMMT-WAS-NICHT!"
3041 # restore former situation
3042 self
.currentLineItem
= cLI
3043 self
.currentLine
= cL
3045 if pl
== [(0, 0), (0, 0)]:
3049 screen
._drawline
(cLI
, pl
, fill
=usepc
, width
=ps
)
3051 todelete
= [i
for i
in self
.items
if (i
not in items
) and
3052 (screen
._type
(i
) == "line")]
3055 self
.items
.remove(i
)
3058 if self
._speed
and screen
._tracing
== 1:
3060 diffsq
= (diff
[0]*screen
.xscale
)**2 + (diff
[1]*screen
.yscale
)**2
3061 nhops
= 1+int((diffsq
**0.5)/(3*(1.1**self
._speed
)*self
._speed
))
3062 delta
= diff
* (1.0/nhops
)
3063 for n
in range(1, nhops
):
3068 self
._position
= new
+ delta
* n
3070 screen
._drawline
(self
.drawingLineItem
,
3071 (start
, self
._position
),
3075 screen
._drawline
(self
.drawingLineItem
, ((0, 0), (0, 0)),
3077 # Turtle now at position old,
3078 self
._position
= old
3079 ## if undo is done during crating a polygon, the last vertex
3080 ## will be deleted. if the polygon is entirel deleted,
3081 ## creatigPoly will be set to False.
3082 ## Polygons created before the last one will not be affected by undo()
3083 if self
._creatingPoly
:
3084 if len(self
._poly
) > 0:
3086 if self
._poly
== []:
3087 self
._creatingPoly
= False
3090 if self
._fillpath
== []:
3091 self
._fillpath
= None
3092 print "Unwahrscheinlich in _undogoto!"
3093 elif self
._fillpath
is not None:
3094 self
._fillpath
.pop()
3095 self
._update
() #count=True)
3097 def _rotate(self
, angle
):
3098 """Turns pen clockwise by angle.
3101 self
.undobuffer
.push(("rot", angle
, self
._degreesPerAU
))
3102 angle
*= self
._degreesPerAU
3103 neworient
= self
._orient
.rotate(angle
)
3104 tracing
= self
.screen
._tracing
3105 if tracing
== 1 and self
._speed
> 0:
3106 anglevel
= 3.0 * self
._speed
3107 steps
= 1 + int(abs(angle
)/anglevel
)
3108 delta
= 1.0*angle
/steps
3109 for _
in range(steps
):
3110 self
._orient
= self
._orient
.rotate(delta
)
3112 self
._orient
= neworient
3115 def _newLine(self
, usePos
=True):
3116 """Closes current line item and starts a new one.
3117 Remark: if current line became too long, animation
3118 performance (via _drawline) slowed down considerably.
3120 if len(self
.currentLine
) > 1:
3121 self
.screen
._drawline
(self
.currentLineItem
, self
.currentLine
,
3122 self
._pencolor
, self
._pensize
)
3123 self
.currentLineItem
= self
.screen
._createline
()
3124 self
.items
.append(self
.currentLineItem
)
3126 self
.screen
._drawline
(self
.currentLineItem
, top
=True)
3127 self
.currentLine
= []
3129 self
.currentLine
= [self
._position
]
3131 def fill(self
, flag
=None):
3132 """Call fill(True) before drawing a shape to fill, fill(False) when done.
3135 flag -- True/False (or 1/0 respectively)
3137 Call fill(True) before drawing the shape you want to fill,
3138 and fill(False) when done.
3139 When used without argument: return fillstate (True if filling,
3142 Example (for a Turtle instance named turtle):
3143 >>> turtle.fill(True)
3144 >>> turtle.forward(100)
3146 >>> turtle.forward(100)
3148 >>> turtle.forward(100)
3150 >>> turtle.forward(100)
3151 >>> turtle.fill(False)
3153 filling
= isinstance(self
._fillpath
, list)
3156 screen
= self
.screen
3157 entry1
= entry2
= ()
3159 if len(self
._fillpath
) > 2:
3160 self
.screen
._drawpoly
(self
._fillitem
, self
._fillpath
,
3161 fill
=self
._fillcolor
)
3162 entry1
= ("dofill", self
._fillitem
)
3164 self
._fillitem
= self
.screen
._createpoly
()
3165 self
.items
.append(self
._fillitem
)
3166 self
._fillpath
= [self
._position
]
3167 entry2
= ("beginfill", self
._fillitem
) # , self._fillpath)
3170 self
._fillitem
= self
._fillpath
= None
3174 self
.undobuffer
.push(entry2
)
3177 self
.undobuffer
.push(entry1
)
3179 self
.undobuffer
.push(["seq", entry1
, entry2
])
3182 def begin_fill(self
):
3183 """Called just before drawing a shape to be filled.
3187 Example (for a Turtle instance named turtle):
3188 >>> turtle.begin_fill()
3189 >>> turtle.forward(100)
3191 >>> turtle.forward(100)
3193 >>> turtle.forward(100)
3195 >>> turtle.forward(100)
3196 >>> turtle.end_fill()
3201 """Fill the shape drawn after the call begin_fill().
3205 Example (for a Turtle instance named turtle):
3206 >>> turtle.begin_fill()
3207 >>> turtle.forward(100)
3209 >>> turtle.forward(100)
3211 >>> turtle.forward(100)
3213 >>> turtle.forward(100)
3214 >>> turtle.end_fill()
3218 def dot(self
, size
=None, *color
):
3219 """Draw a dot with diameter size, using color.
3222 size -- an integer >= 1 (if given)
3223 color -- a colorstring or a numeric color tuple
3225 Draw a circular dot with diameter size, using color.
3226 If size is not given, the maximum of pensize+4 and 2*pensize is used.
3228 Example (for a Turtle instance named turtle):
3230 >>> turtle.fd(50); turtle.dot(20, "blue"); turtle.fd(50)
3232 #print "dot-1:", size, color
3234 if isinstance(size
, (str, tuple)):
3235 color
= self
._colorstr
(size
)
3236 size
= self
._pensize
+ max(self
._pensize
, 4)
3238 color
= self
._pencolor
3240 size
= self
._pensize
+ max(self
._pensize
, 4)
3243 size
= self
._pensize
+ max(self
._pensize
, 4)
3244 color
= self
._colorstr
(color
)
3245 #print "dot-2:", size, color
3246 if hasattr(self
.screen
, "_dot"):
3247 item
= self
.screen
._dot
(self
._position
, size
, color
)
3248 #print "dot:", size, color, "item:", item
3249 self
.items
.append(item
)
3251 self
.undobuffer
.push(("dot", item
))
3255 self
.undobuffer
.push(["seq"])
3256 self
.undobuffer
.cumulate
= True
3258 if self
.resizemode() == 'auto':
3262 self
.pencolor(color
)
3267 self
.undobuffer
.cumulate
= False
3269 def _write(self
, txt
, align
, font
):
3270 """Performs the writing for write()
3272 item
, end
= self
.screen
._write
(self
._position
, txt
, align
, font
,
3274 self
.items
.append(item
)
3276 self
.undobuffer
.push(("wri", item
))
3279 def write(self
, arg
, move
=False, align
="left", font
=("Arial", 8, "normal")):
3280 """Write text at the current turtle position.
3283 arg -- info, which is to be written to the TurtleScreen
3284 move (optional) -- True/False
3285 align (optional) -- one of the strings "left", "center" or right"
3286 font (optional) -- a triple (fontname, fontsize, fonttype)
3288 Write text - the string representation of arg - at the current
3289 turtle position according to align ("left", "center" or right")
3290 and with the given font.
3291 If move is True, the pen is moved to the bottom-right corner
3292 of the text. By default, move is False.
3294 Example (for a Turtle instance named turtle):
3295 >>> turtle.write('Home = ', True, align="center")
3296 >>> turtle.write((0,0), True)
3299 self
.undobuffer
.push(["seq"])
3300 self
.undobuffer
.cumulate
= True
3301 end
= self
._write
(str(arg
), align
.lower(), font
)
3306 self
.undobuffer
.cumulate
= False
3308 def begin_poly(self
):
3309 """Start recording the vertices of a polygon.
3313 Start recording the vertices of a polygon. Current turtle position
3314 is first point of polygon.
3316 Example (for a Turtle instance named turtle):
3317 >>> turtle.begin_poly()
3319 self
._poly
= [self
._position
]
3320 self
._creatingPoly
= True
3323 """Stop recording the vertices of a polygon.
3327 Stop recording the vertices of a polygon. Current turtle position is
3328 last point of polygon. This will be connected with the first point.
3330 Example (for a Turtle instance named turtle):
3331 >>> turtle.end_poly()
3333 self
._creatingPoly
= False
3336 """Return the lastly recorded polygon.
3340 Example (for a Turtle instance named turtle):
3341 >>> p = turtle.get_poly()
3342 >>> turtle.register_shape("myFavouriteShape", p)
3344 ## check if there is any poly? -- 1st solution:
3345 if self
._poly
is not None:
3346 return tuple(self
._poly
)
3348 def getscreen(self
):
3349 """Return the TurtleScreen object, the turtle is drawing on.
3353 Return the TurtleScreen object, the turtle is drawing on.
3354 So TurtleScreen-methods can be called for that object.
3356 Example (for a Turtle instance named turtle):
3357 >>> ts = turtle.getscreen()
3359 <turtle.TurtleScreen object at 0x0106B770>
3360 >>> ts.bgcolor("pink")
3364 def getturtle(self
):
3365 """Return the Turtleobject itself.
3369 Only reasonable use: as a function to return the 'anonymous turtle':
3372 >>> pet = getturtle()
3375 <turtle.Turtle object at 0x0187D810>
3377 [<turtle.Turtle object at 0x0187D810>]
3384 ################################################################
3385 ### screen oriented methods recurring to methods of TurtleScreen
3386 ################################################################
3388 def window_width(self
):
3389 """ Returns the width of the turtle window.
3393 Example (for a TurtleScreen instance named screen):
3394 >>> screen.window_width()
3397 return self
.screen
._window
_size
()[0]
3399 def window_height(self
):
3400 """ Return the height of the turtle window.
3404 Example (for a TurtleScreen instance named screen):
3405 >>> screen.window_height()
3408 return self
.screen
._window
_size
()[1]
3410 def _delay(self
, delay
=None):
3411 """Set delay value which determines speed of turtle animation.
3413 return self
.screen
.delay(delay
)
3415 ##### event binding methods #####
3417 def onclick(self
, fun
, btn
=1, add
=None):
3418 """Bind fun to mouse-click event on this turtle on canvas.
3421 fun -- a function with two arguments, to which will be assigned
3422 the coordinates of the clicked point on the canvas.
3423 num -- number of the mouse-button defaults to 1 (left mouse button).
3424 add -- True or False. If True, new binding will be added, otherwise
3425 it will replace a former binding.
3427 Example for the anonymous turtle, i. e. the procedural way:
3432 >>> onclick(turn) # Now clicking into the turtle will turn it.
3433 >>> onclick(None) # event-binding will be removed
3435 self
.screen
._onclick
(self
.turtle
._item
, fun
, btn
, add
)
3438 def onrelease(self
, fun
, btn
=1, add
=None):
3439 """Bind fun to mouse-button-release event on this turtle on canvas.
3442 fun -- a function with two arguments, to which will be assigned
3443 the coordinates of the clicked point on the canvas.
3444 num -- number of the mouse-button defaults to 1 (left mouse button).
3446 Example (for a MyTurtle instance named joe):
3447 >>> class MyTurtle(Turtle):
3449 self.fillcolor("red")
3450 def unglow(self,x,y):
3453 >>> joe = MyTurtle()
3454 >>> joe.onclick(joe.glow)
3455 >>> joe.onrelease(joe.unglow)
3456 ### clicking on joe turns fillcolor red,
3457 ### unclicking turns it to transparent.
3459 self
.screen
._onrelease
(self
.turtle
._item
, fun
, btn
, add
)
3462 def ondrag(self
, fun
, btn
=1, add
=None):
3463 """Bind fun to mouse-move event on this turtle on canvas.
3466 fun -- a function with two arguments, to which will be assigned
3467 the coordinates of the clicked point on the canvas.
3468 num -- number of the mouse-button defaults to 1 (left mouse button).
3470 Every sequence of mouse-move-events on a turtle is preceded by a
3471 mouse-click event on that turtle.
3473 Example (for a Turtle instance named turtle):
3474 >>> turtle.ondrag(turtle.goto)
3476 ### Subsequently clicking and dragging a Turtle will
3477 ### move it across the screen thereby producing handdrawings
3478 ### (if pen is down).
3480 self
.screen
._ondrag
(self
.turtle
._item
, fun
, btn
, add
)
3483 def _undo(self
, action
, data
):
3484 """Does the main part of the work for undo()
3486 if self
.undobuffer
is None:
3489 angle
, degPAU
= data
3490 self
._rotate
(-angle
*degPAU
/self
._degreesPerAU
)
3491 dummy
= self
.undobuffer
.pop()
3492 elif action
== "stamp":
3494 self
.clearstamp(stitem
)
3495 elif action
== "go":
3496 self
._undogoto
(data
)
3497 elif action
in ["wri", "dot"]:
3499 self
.screen
._delete
(item
)
3500 self
.items
.remove(item
)
3501 elif action
== "dofill":
3503 self
.screen
._drawpoly
(item
, ((0, 0),(0, 0),(0, 0)),
3504 fill
="", outline
="")
3505 elif action
== "beginfill":
3507 self
._fillitem
= self
._fillpath
= None
3508 self
.screen
._delete
(item
)
3509 self
.items
.remove(item
)
3510 elif action
== "pen":
3511 TPen
.pen(self
, data
[0])
3512 self
.undobuffer
.pop()
3515 """undo (repeatedly) the last turtle action.
3519 undo (repeatedly) the last turtle action.
3520 Number of available undo actions is determined by the size of
3523 Example (for a Turtle instance named turtle):
3524 >>> for i in range(4):
3525 turtle.fd(50); turtle.lt(80)
3527 >>> for i in range(8):
3530 if self
.undobuffer
is None:
3532 item
= self
.undobuffer
.pop()
3538 self
._undo
(item
[0], item
[1:])
3540 self
._undo
(action
, data
)
3542 turtlesize
= shapesize
3546 ### Screen - Singleton ########################
3549 """Return the singleton screen object.
3550 If none exists at the moment, create a new one and return it,
3551 else return the existing one."""
3552 if Turtle
._screen
is None:
3553 Turtle
._screen
= _Screen()
3554 return Turtle
._screen
3556 class _Screen(TurtleScreen
):
3560 _title
= _CFG
["title"]
3563 # XXX there is no need for this code to be conditional,
3564 # as there will be only a single _Screen instance, anyway
3565 # XXX actually, the turtle demo is injecting root window,
3566 # so perhaps the conditional creation of a root should be
3567 # preserved (perhaps by passing it as an optional parameter)
3568 if _Screen
._root
is None:
3569 _Screen
._root
= self
._root
= _Root()
3570 self
._root
.title(_Screen
._title
)
3571 self
._root
.ondestroy(self
._destroy
)
3572 if _Screen
._canvas
is None:
3573 width
= _CFG
["width"]
3574 height
= _CFG
["height"]
3575 canvwidth
= _CFG
["canvwidth"]
3576 canvheight
= _CFG
["canvheight"]
3577 leftright
= _CFG
["leftright"]
3578 topbottom
= _CFG
["topbottom"]
3579 self
._root
.setupcanvas(width
, height
, canvwidth
, canvheight
)
3580 _Screen
._canvas
= self
._root
._getcanvas
()
3581 TurtleScreen
.__init
__(self
, _Screen
._canvas
)
3582 self
.setup(width
, height
, leftright
, topbottom
)
3584 def setup(self
, width
=_CFG
["width"], height
=_CFG
["height"],
3585 startx
=_CFG
["leftright"], starty
=_CFG
["topbottom"]):
3586 """ Set the size and position of the main window.
3589 width: as integer a size in pixels, as float a fraction of the screen.
3590 Default is 50% of screen.
3591 height: as integer the height in pixels, as float a fraction of the
3592 screen. Default is 75% of screen.
3593 startx: if positive, starting position in pixels from the left
3594 edge of the screen, if negative from the right edge
3595 Default, startx=None is to center window horizontally.
3596 starty: if positive, starting position in pixels from the top
3597 edge of the screen, if negative from the bottom edge
3598 Default, starty=None is to center window vertically.
3600 Examples (for a Screen instance named screen):
3601 >>> screen.setup (width=200, height=200, startx=0, starty=0)
3603 sets window to 200x200 pixels, in upper left of screen
3605 >>> screen.setup(width=.75, height=0.5, startx=None, starty=None)
3607 sets window to 75% of screen by 50% of screen and centers
3609 if not hasattr(self
._root
, "set_geometry"):
3611 sw
= self
._root
.win_width()
3612 sh
= self
._root
.win_height()
3613 if isinstance(width
, float) and 0 <= width
<= 1:
3616 startx
= (sw
- width
) / 2
3617 if isinstance(height
, float) and 0 <= height
<= 1:
3620 starty
= (sh
- height
) / 2
3621 self
._root
.set_geometry(width
, height
, startx
, starty
)
3624 def title(self
, titlestring
):
3625 """Set title of turtle-window
3628 titlestring -- a string, to appear in the titlebar of the
3629 turtle graphics window.
3631 This is a method of Screen-class. Not available for TurtleScreen-
3634 Example (for a Screen instance named screen):
3635 >>> screen.title("Welcome to the turtle-zoo!")
3637 if _Screen
._root
is not None:
3638 _Screen
._root
.title(titlestring
)
3639 _Screen
._title
= titlestring
3643 if root
is _Screen
._root
:
3645 Turtle
._screen
= None
3646 _Screen
._root
= None
3647 _Screen
._canvas
= None
3648 TurtleScreen
._RUNNING
= True
3652 """Shut the turtlegraphics window.
3654 Example (for a TurtleScreen instance named screen):
3659 def exitonclick(self
):
3660 """Go into mainloop until the mouse is clicked.
3664 Bind bye() method to mouseclick on TurtleScreen.
3665 If "using_IDLE" - value in configuration dictionary is False
3666 (default value), enter mainloop.
3667 If IDLE with -n switch (no subprocess) is used, this value should be
3668 set to True in turtle.cfg. In this case IDLE's mainloop
3669 is active also for the client script.
3671 This is a method of the Screen-class and not available for
3672 TurtleScreen instances.
3674 Example (for a Screen instance named screen):
3675 >>> screen.exitonclick()
3678 def exitGracefully(x
, y
):
3679 """Screen.bye() with two dummy-parameters"""
3681 self
.onclick(exitGracefully
)
3682 if _CFG
["using_IDLE"]:
3686 except AttributeError:
3690 class Turtle(RawTurtle
):
3691 """RawTurtle auto-crating (scrolled) canvas.
3693 When a Turtle object is created or a function derived from some
3694 Turtle method is called a TurtleScreen object is automatically created.
3700 shape
=_CFG
["shape"],
3701 undobuffersize
=_CFG
["undobuffersize"],
3702 visible
=_CFG
["visible"]):
3703 if Turtle
._screen
is None:
3704 Turtle
._screen
= Screen()
3705 RawTurtle
.__init
__(self
, Turtle
._screen
,
3707 undobuffersize
=undobuffersize
,
3713 """Create the 'anonymous' turtle if not already present."""
3714 if Turtle
._pen
is None:
3715 Turtle
._pen
= Turtle()
3719 """Create a TurtleScreen if not already present."""
3720 if Turtle
._screen
is None:
3721 Turtle
._screen
= Screen()
3722 return Turtle
._screen
3724 def write_docstringdict(filename
="turtle_docstringdict"):
3725 """Create and write docstring-dictionary to file.
3728 filename -- a string, used as filename
3729 default value is turtle_docstringdict
3731 Has to be called explicitely, (not used by the turtle-graphics classes)
3732 The docstring dictionary will be written to the Python script <filname>.py
3733 It is intended to serve as a template for translation of the docstrings
3734 into different languages.
3738 for methodname
in _tg_screen_functions
:
3739 key
= "_Screen."+methodname
3740 docsdict
[key
] = eval(key
).__doc
__
3741 for methodname
in _tg_turtle_functions
:
3742 key
= "Turtle."+methodname
3743 docsdict
[key
] = eval(key
).__doc
__
3745 f
= open("%s.py" % filename
,"w")
3746 keys
= sorted([x
for x
in docsdict
.keys()
3747 if x
.split('.')[1] not in _alias_list
])
3748 f
.write('docsdict = {\n\n')
3749 for key
in keys
[:-1]:
3750 f
.write('%s :\n' % repr(key
))
3751 f
.write(' """%s\n""",\n\n' % docsdict
[key
])
3753 f
.write('%s :\n' % repr(key
))
3754 f
.write(' """%s\n"""\n\n' % docsdict
[key
])
3758 def read_docstrings(lang
):
3759 """Read in docstrings from lang-specific docstring dictionary.
3761 Transfer docstrings, translated to lang, from a dictionary-file
3762 to the methods of classes Screen and Turtle and - in revised form -
3763 to the corresponding functions.
3765 modname
= "turtle_docstringdict_%(language)s" % {'language':lang
.lower()}
3766 module
= __import__(modname
)
3767 docsdict
= module
.docsdict
3768 for key
in docsdict
:
3771 eval(key
).im_func
.__doc
__ = docsdict
[key
]
3773 print "Bad docstring-entry: %s" % key
3775 _LANGUAGE
= _CFG
["language"]
3778 if _LANGUAGE
!= "english":
3779 read_docstrings(_LANGUAGE
)
3781 print "Cannot find docsdict for", _LANGUAGE
3783 print ("Unknown Error when trying to import %s-docstring-dictionary" %
3787 def getmethparlist(ob
):
3788 "Get strings describing the arguments for the given object"
3789 argText1
= argText2
= ""
3790 # bit of a hack for methods - turn it into a function
3791 # but we drop the "self" param.
3792 if type(ob
)==types
.MethodType
:
3798 # Try and build one for Python defined functions
3799 if type(fob
) in [types
.FunctionType
, types
.LambdaType
]:
3801 counter
= fob
.func_code
.co_argcount
3802 items2
= list(fob
.func_code
.co_varnames
[argOffset
:counter
])
3803 realArgs
= fob
.func_code
.co_varnames
[argOffset
:counter
]
3804 defaults
= fob
.func_defaults
or []
3805 defaults
= list(map(lambda name
: "=%s" % repr(name
), defaults
))
3806 defaults
= [""] * (len(realArgs
)-len(defaults
)) + defaults
3807 items1
= map(lambda arg
, dflt
: arg
+dflt
, realArgs
, defaults
)
3808 if fob
.func_code
.co_flags
& 0x4:
3809 items1
.append("*"+fob
.func_code
.co_varnames
[counter
])
3810 items2
.append("*"+fob
.func_code
.co_varnames
[counter
])
3812 if fob
.func_code
.co_flags
& 0x8:
3813 items1
.append("**"+fob
.func_code
.co_varnames
[counter
])
3814 items2
.append("**"+fob
.func_code
.co_varnames
[counter
])
3815 argText1
= ", ".join(items1
)
3816 argText1
= "(%s)" % argText1
3817 argText2
= ", ".join(items2
)
3818 argText2
= "(%s)" % argText2
3821 return argText1
, argText2
3823 def _turtle_docrevise(docstr
):
3824 """To reduce docstrings from RawTurtle class for functions
3829 turtlename
= _CFG
["exampleturtle"]
3830 newdocstr
= docstr
.replace("%s." % turtlename
,"")
3831 parexp
= re
.compile(r
' \(.+ %s\):' % turtlename
)
3832 newdocstr
= parexp
.sub(":", newdocstr
)
3835 def _screen_docrevise(docstr
):
3836 """To reduce docstrings from TurtleScreen class for functions
3841 screenname
= _CFG
["examplescreen"]
3842 newdocstr
= docstr
.replace("%s." % screenname
,"")
3843 parexp
= re
.compile(r
' \(.+ %s\):' % screenname
)
3844 newdocstr
= parexp
.sub(":", newdocstr
)
3847 ## The following mechanism makes all methods of RawTurtle and Turtle available
3848 ## as functions. So we can enhance, change, add, delete methods to these
3849 ## classes and do not need to change anything here.
3852 for methodname
in _tg_screen_functions
:
3853 pl1
, pl2
= getmethparlist(eval('_Screen.' + methodname
))
3855 print ">>>>>>", pl1
, pl2
3857 defstr
= ("def %(key)s%(pl1)s: return _getscreen().%(key)s%(pl2)s" %
3858 {'key':methodname
, 'pl1':pl1
, 'pl2':pl2
})
3860 eval(methodname
).__doc
__ = _screen_docrevise(eval('_Screen.'+methodname
).__doc
__)
3862 for methodname
in _tg_turtle_functions
:
3863 pl1
, pl2
= getmethparlist(eval('Turtle.' + methodname
))
3865 print ">>>>>>", pl1
, pl2
3867 defstr
= ("def %(key)s%(pl1)s: return _getpen().%(key)s%(pl2)s" %
3868 {'key':methodname
, 'pl1':pl1
, 'pl2':pl2
})
3870 eval(methodname
).__doc
__ = _turtle_docrevise(eval('Turtle.'+methodname
).__doc
__)
3873 done
= mainloop
= TK
.mainloop
3874 del pl1
, pl2
, defstr
3876 if __name__
== "__main__":
3884 """Demo of old turtle.py - module"""
3890 # draw 3 squares; the last filled
3906 # move out of the way
3916 write("startstart", 1)
3937 """Demo of some new features."""
3941 setheading(towards(0, 0))
3942 radius
= distance(0, 0)/2.0
3947 write("wait a moment...")
3948 while undobufferentries():
3957 for i
in range(-2, 16):
3960 fillcolor(255-15*i
, 0, 15*i
)
3966 speed((speed()+1)%12)
3974 color("red","yellow")
3990 tri
.resizemode("auto")
3992 turtle
.resizemode("auto")
3993 turtle
.shape("turtle")
3998 turtle
.goto(280, 40)
4002 turtle
.color("blue","orange")
4005 setheading(towards(turtle
))
4007 while tri
.distance(turtle
) > 4:
4010 tri
.setheading(tri
.towards(turtle
))
4017 tri
.write("CAUGHT! ", font
=("Arial", 16, "bold"), align
="right")
4018 tri
.pencolor("black")
4021 def baba(xdummy
, ydummy
):
4027 while undobufferentries():
4031 tri
.write(" Click me!", font
= ("Courier", 12, "bold") )
4032 tri
.onclick(baba
, 1)