summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2009-05-05 08:14:33 +0000
committerGeorg Brandl <georg@python.org>2009-05-05 08:14:33 +0000
commit658fe19409746b2ed8979c8775d3e0673df76918 (patch)
treeda4916844b98a678b5cb7d73c8fbbf46aaefb4f3
parent4407d637749df253344588019dbbc60a0610cde1 (diff)
downloadcpython-658fe19409746b2ed8979c8775d3e0673df76918.tar.gz
#5923: update turtle module to version 1.1.
-rw-r--r--Demo/turtle/tdemo_nim.py227
-rw-r--r--Demo/turtle/tdemo_round_dance.py90
-rw-r--r--Doc/library/turtle.rst187
-rw-r--r--Lib/turtle.py466
-rw-r--r--Misc/NEWS3
5 files changed, 775 insertions, 198 deletions
diff --git a/Demo/turtle/tdemo_nim.py b/Demo/turtle/tdemo_nim.py
new file mode 100644
index 0000000000..b0edf44714
--- /dev/null
+++ b/Demo/turtle/tdemo_nim.py
@@ -0,0 +1,227 @@
+""" turtle-example-suite:
+
+ tdemo_nim.py
+
+Play nim against the computer. The player
+who takes the last stick is the winner.
+
+Implements the model-view-controller
+design pattern.
+"""
+
+
+import turtle
+import random
+import time
+
+SCREENWIDTH = 640
+SCREENHEIGHT = 480
+
+MINSTICKS = 7
+MAXSTICKS = 31
+
+HUNIT = SCREENHEIGHT // 12
+WUNIT = SCREENWIDTH // ((MAXSTICKS // 5) * 11 + (MAXSTICKS % 5) * 2)
+
+SCOLOR = (63, 63, 31)
+HCOLOR = (255, 204, 204)
+COLOR = (204, 204, 255)
+
+def randomrow():
+ return random.randint(MINSTICKS, MAXSTICKS)
+
+def computerzug(state):
+ xored = state[0] ^ state[1] ^ state[2]
+ if xored == 0:
+ return randommove(state)
+ for z in range(3):
+ s = state[z] ^ xored
+ if s <= state[z]:
+ move = (z, s)
+ return move
+
+def randommove(state):
+ m = max(state)
+ while True:
+ z = random.randint(0,2)
+ if state[z] > (m > 1):
+ break
+ rand = random.randint(m > 1, state[z]-1)
+ return z, rand
+
+
+class NimModel(object):
+ def __init__(self, game):
+ self.game = game
+
+ def setup(self):
+ if self.game.state not in [Nim.CREATED, Nim.OVER]:
+ return
+ self.sticks = [randomrow(), randomrow(), randomrow()]
+ self.player = 0
+ self.winner = None
+ self.game.view.setup()
+ self.game.state = Nim.RUNNING
+
+ def move(self, row, col):
+ maxspalte = self.sticks[row]
+ self.sticks[row] = col
+ self.game.view.notify_move(row, col, maxspalte, self.player)
+ if self.game_over():
+ self.game.state = Nim.OVER
+ self.winner = self.player
+ self.game.view.notify_over()
+ elif self.player == 0:
+ self.player = 1
+ row, col = computerzug(self.sticks)
+ self.move(row, col)
+ self.player = 0
+
+ def game_over(self):
+ return self.sticks == [0, 0, 0]
+
+ def notify_move(self, row, col):
+ if self.sticks[row] <= col:
+ return
+ self.move(row, col)
+
+
+class Stick(turtle.Turtle):
+ def __init__(self, row, col, game):
+ turtle.Turtle.__init__(self, visible=False)
+ self.row = row
+ self.col = col
+ self.game = game
+ x, y = self.coords(row, col)
+ self.shape("square")
+ self.shapesize(HUNIT/10.0, WUNIT/20.0)
+ self.speed(0)
+ self.pu()
+ self.goto(x,y)
+ self.color("white")
+ self.showturtle()
+
+ def coords(self, row, col):
+ packet, remainder = divmod(col, 5)
+ x = (3 + 11 * packet + 2 * remainder) * WUNIT
+ y = (2 + 3 * row) * HUNIT
+ return x - SCREENWIDTH // 2 + WUNIT // 2, SCREENHEIGHT // 2 - y - HUNIT // 2
+
+ def makemove(self, x, y):
+ if self.game.state != Nim.RUNNING:
+ return
+ self.game.controller.notify_move(self.row, self.col)
+
+
+class NimView(object):
+ def __init__(self, game):
+ self.game = game
+ self.screen = game.screen
+ self.model = game.model
+ self.screen.colormode(255)
+ self.screen.tracer(False)
+ self.screen.bgcolor((240, 240, 255))
+ self.writer = turtle.Turtle(visible=False)
+ self.writer.pu()
+ self.writer.speed(0)
+ self.sticks = {}
+ for row in range(3):
+ for col in range(MAXSTICKS):
+ self.sticks[(row, col)] = Stick(row, col, game)
+ self.display("... a moment please ...")
+ self.screen.tracer(True)
+
+ def display(self, msg1, msg2=None):
+ self.screen.tracer(False)
+ self.writer.clear()
+ if msg2 is not None:
+ self.writer.goto(0, - SCREENHEIGHT // 2 + 48)
+ self.writer.pencolor("red")
+ self.writer.write(msg2, align="center", font=("Courier",18,"bold"))
+ self.writer.goto(0, - SCREENHEIGHT // 2 + 20)
+ self.writer.pencolor("black")
+ self.writer.write(msg1, align="center", font=("Courier",14,"bold"))
+ self.screen.tracer(True)
+
+
+ def setup(self):
+ self.screen.tracer(False)
+ for row in range(3):
+ for col in range(self.model.sticks[row]):
+ self.sticks[(row, col)].color(SCOLOR)
+ for row in range(3):
+ for col in range(self.model.sticks[row], MAXSTICKS):
+ self.sticks[(row, col)].color("white")
+ self.display("Your turn! Click leftmost stick to remove.")
+ self.screen.tracer(True)
+
+ def notify_move(self, row, col, maxspalte, player):
+ if player == 0:
+ farbe = HCOLOR
+ for s in range(col, maxspalte):
+ self.sticks[(row, s)].color(farbe)
+ else:
+ self.display(" ... thinking ... ")
+ time.sleep(0.5)
+ self.display(" ... thinking ... aaah ...")
+ farbe = COLOR
+ for s in range(maxspalte-1, col-1, -1):
+ time.sleep(0.2)
+ self.sticks[(row, s)].color(farbe)
+ self.display("Your turn! Click leftmost stick to remove.")
+
+ def notify_over(self):
+ if self.game.model.winner == 0:
+ msg2 = "Congrats. You're the winner!!!"
+ else:
+ msg2 = "Sorry, the computer is the winner."
+ self.display("To play again press space bar. To leave press ESC.", msg2)
+
+ def clear(self):
+ if self.game.state == Nim.OVER:
+ self.screen.clear()
+
+class NimController(object):
+
+ def __init__(self, game):
+ self.game = game
+ self.sticks = game.view.sticks
+ self.BUSY = False
+ for stick in self.sticks.values():
+ stick.onclick(stick.makemove)
+ self.game.screen.onkey(self.game.model.setup, "space")
+ self.game.screen.onkey(self.game.view.clear, "Escape")
+ self.game.view.display("Press space bar to start game")
+ self.game.screen.listen()
+
+ def notify_move(self, row, col):
+ if self.BUSY:
+ return
+ self.BUSY = True
+ self.game.model.notify_move(row, col)
+ self.BUSY = False
+
+class Nim(object):
+ CREATED = 0
+ RUNNING = 1
+ OVER = 2
+ def __init__(self, screen):
+ self.state = Nim.CREATED
+ self.screen = screen
+ self.model = NimModel(self)
+ self.view = NimView(self)
+ self.controller = NimController(self)
+
+
+mainscreen = turtle.Screen()
+mainscreen.mode("standard")
+mainscreen.setup(SCREENWIDTH, SCREENHEIGHT)
+
+def main():
+ nim = Nim(mainscreen)
+ return "EVENTLOOP!"
+
+if __name__ == "__main__":
+ main()
+ turtle.mainloop()
+
diff --git a/Demo/turtle/tdemo_round_dance.py b/Demo/turtle/tdemo_round_dance.py
new file mode 100644
index 0000000000..67676d055c
--- /dev/null
+++ b/Demo/turtle/tdemo_round_dance.py
@@ -0,0 +1,90 @@
+""" turtle-example-suite:
+
+ tdemo_round_dance.py
+
+(Needs version 1.1 of the turtle module that
+comes with Python 3.1)
+
+Dancing turtles have a compound shape
+consisting of a series of triangles of
+decreasing size.
+
+Turtles march along a circle while rotating
+pairwise in opposite direction, with one
+exception. Does that breaking of symmetry
+enhance the attractiveness of the example?
+
+Press any key to stop the animation.
+
+Technically: demonstrates use of compound
+shapes, transformation of shapes as well as
+cloning turtles. The animation is
+controlled through update().
+"""
+
+from turtle import *
+
+def stop():
+ global running
+ running = False
+
+def main():
+ global running
+ clearscreen()
+ bgcolor("gray10")
+ tracer(False)
+ shape("triangle")
+ f = 0.793402
+ phi = 9.064678
+ s = 5
+ c = 1
+ # create compound shape
+ sh = Shape("compound")
+ for i in range(10):
+ shapesize(s)
+ p =get_shapepoly()
+ s *= f
+ c *= f
+ tilt(-phi)
+ sh.addcomponent(p, (c, 0.25, 1-c), "black")
+ register_shape("multitri", sh)
+ # create dancers
+ shapesize(1)
+ shape("multitri")
+ pu()
+ setpos(0, -200)
+ dancers = []
+ for i in range(180):
+ fd(7)
+ tilt(-4)
+ lt(2)
+ update()
+ if i % 12 == 0:
+ dancers.append(clone())
+ home()
+ # dance
+ running = True
+ onkeypress(stop)
+ listen()
+ cs = 1
+ while running:
+ ta = -4
+ for dancer in dancers:
+ dancer.fd(7)
+ dancer.lt(2)
+ dancer.tilt(ta)
+ ta = -4 if ta > 0 else 2
+ if cs < 180:
+ right(4)
+ shapesize(cs)
+ cs *= 1.005
+ update()
+ return "DONE!"
+
+if __name__=='__main__':
+ print(main())
+ mainloop()
+
+
+
+
diff --git a/Doc/library/turtle.rst b/Doc/library/turtle.rst
index 001f349fec..b3387b6d88 100644
--- a/Doc/library/turtle.rst
+++ b/Doc/library/turtle.rst
@@ -149,9 +149,12 @@ Turtle state
| :func:`shape`
| :func:`resizemode`
| :func:`shapesize` | :func:`turtlesize`
+ | :func:`shearfactor`
| :func:`settiltangle`
| :func:`tiltangle`
| :func:`tilt`
+ | :func:`shapetransform`
+ | :func:`get_shapepoly`
Using events
| :func:`onclick`
@@ -187,9 +190,11 @@ Animation control
Using screen events
| :func:`listen`
- | :func:`onkey`
+ | :func:`onkey` | :func:`onkeyrelease`
+ | :func:`onkeypress`
| :func:`onclick` | :func:`onscreenclick`
| :func:`ontimer`
+ | :func:`mainloop`
Settings and special methods
| :func:`mode`
@@ -201,6 +206,10 @@ Settings and special methods
| :func:`window_height`
| :func:`window_width`
+Input methods
+ | :func:`textinput`
+ | :func:`numinput`
+
Methods specific to Screen
| :func:`bye`
| :func:`exitonclick`
@@ -1157,6 +1166,26 @@ Appearance
(5, 5, 8)
+.. function:: shearfactor(self, shear=None):
+
+ :param shear: number (optional)
+
+ Set or return the current shearfactor. Shear the turtleshape according to
+ the given shearfactor shear, which is the tangent of the shear angle.
+ Do *not* change the turtle's heading (direction of movement).
+ If shear is not given: return the current shearfactor, i. e. the
+ tangent of the shear angle, by which lines parallel to the
+ heading of the turtle are sheared.
+
+ .. doctest::
+
+ >>> turtle.shape("circle")
+ >>> turtle.shapesize(5,2)
+ >>> turtle.shearfactor(0.5)
+ >>> turtle.shearfactor()
+ >>> 0.5
+
+
.. function:: tilt(angle)
:param angle: a number
@@ -1194,10 +1223,19 @@ Appearance
>>> turtle.fd(50)
-.. function:: tiltangle()
+.. function:: tiltangle(angle=None)
- Return the current tilt-angle, i.e. the angle between the orientation of the
- turtleshape and the heading of the turtle (its direction of movement).
+ :param angle: a number (optional)
+
+ Set or return the current tilt-angle. If angle is given, rotate the
+ turtleshape to point in the direction specified by angle,
+ regardless of its current tilt-angle. Do *not* change the turtle's
+ heading (direction of movement).
+ If angle is not given: return the current tilt-angle, i. e. the angle
+ between the orientation of the turtleshape and the heading of the
+ turtle (its direction of movement).
+
+ Deprecated since Python 3.1
.. doctest::
@@ -1209,6 +1247,46 @@ Appearance
45.0
+.. function:: shapetransform(t11=None, t12=None, t21=None, t22=None)
+
+ :param t11: a number (optional)
+ :param t12: a number (optional)
+ :param t21: a number (optional)
+ :param t12: a number (optional)
+
+ Set or return the current transformation matrix of the turtle shape.
+
+ If none of the matrix elements are given, return the transformation
+ matrix as a tuple of 4 elements.
+ Otherwise set the given elements and transform the turtleshape
+ according to the matrix consisting of first row t11, t12 and
+ second row t21, 22. The determinant t11 * t22 - t12 * t21 must not be
+ zero, otherwise an error is raised.
+ Modify stretchfactor, shearfactor and tiltangle according to the
+ given matrix.
+
+ .. doctest::
+
+ >>> turtle.shape("square")
+ >>> turtle.shapesize(4,2)
+ >>> turtle.shearfactor(-0.5)
+ >>> turtle.shapetransform()
+ >>> (4.0, -1.0, -0.0, 2.0)
+
+
+.. function:: get_shapepoly():
+
+ Return the current shape polygon as tuple of coordinate pairs. This
+ can be used to define a new shape or components of a compound shape.
+
+ .. doctest::
+
+ >>> turtle.shape("square")
+ >>> turtle.shapetransform(4, -1, 0, 2)
+ >>> turtle.get_shapepoly()
+ ((50, -20), (30, 20), (-50, 20), (-30, -20))
+
+
Using events
------------
@@ -1595,6 +1673,7 @@ Using screen events
.. function:: onkey(fun, key)
+ onkeyrelease(fun, key)
:param fun: a function with no arguments or ``None``
:param key: a string: key (e.g. "a") or key-symbol (e.g. "space")
@@ -1613,6 +1692,25 @@ Using screen events
>>> screen.listen()
+.. function:: onkeypress(fun, key=None):
+
+ :param fun: a function with no arguments or ``None``
+ :param key: a string: key (e.g. "a") or key-symbol (e.g. "space")
+
+ Bind *fun* to key-press event of key if key is given,
+ or to any key-press-event if no key is given.
+ Remark: in order to be able to register key-events, TurtleScreen
+ must have focus. (See method :func:`listen`.)
+
+ .. doctest::
+
+ >>> def f():
+ ... fd(50)
+ ...
+ >>> screen.onkey(f, "Up")
+ >>> screen.listen()
+
+
.. function:: onclick(fun, btn=1, add=None)
onscreenclick(fun, btn=1, add=None)
@@ -1659,6 +1757,53 @@ Using screen events
>>> running = False
+.. function:: mainloop()
+
+ Starts event loop - calling Tkinter's mainloop function.
+ Must be the last statement in a turtle graphics program.
+ Must *not* be used if a script is run from within IDLE in -n mode
+ (No subprocess) - for interactive use of turtle graphics. ::
+
+ >>> screen.mainloop()
+
+
+Input methods
+-------------
+
+.. function:: textinput(title, prompt)
+
+ :param title: string
+ :param prompt: string
+
+ Pop up a dialog window for input of a string. Parameter title is
+ the title of the dialog window, propmt is a text mostly describing
+ what information to input.
+ Return the string input. If the dialog is canceled, return None. ::
+
+ >>> screen.textinput("NIM", "Name of first player:")
+
+
+.. function:: numinput(self, title, prompt,
+ default=None, minval=None, maxval=None):
+
+ :param title: string
+ :param prompt: string
+ :param default: number (optional)
+ :param prompt: number (optional)
+ :param prompt: number (optional)
+
+ Pop up a dialog window for input of a number. title is the title of the
+ dialog window, prompt is a text mostly describing what numerical information
+ to input. default: default value, minval: minimum value for imput,
+ maxval: maximum value for input
+ The number input must be in the range minval .. maxval if these are
+ given. If not, a hint is issued and the dialog remains open for
+ correction.
+ Return the number input. If the dialog is canceled, return None. ::
+
+ >>> screen.numinput("Poker", "Your stakes:", 1000, minval=10, maxval=10000)
+
+
Settings and special methods
----------------------------
@@ -2159,6 +2304,10 @@ The demoscripts are:
| | | as Hanoi discs |
| | | (shape, shapesize) |
+----------------+------------------------------+-----------------------+
+| nim | play the classical nim game | turtles as nimsticks, |
+| | with three heaps of sticks | event driven (mouse, |
+| | against the computer. | keyboard) |
++----------------+------------------------------+-----------------------+
| paint | super minimalistic | :func:`onclick` |
| | drawing program | |
+----------------+------------------------------+-----------------------+
@@ -2171,6 +2320,10 @@ The demoscripts are:
| planet_and_moon| simulation of | compound shapes, |
| | gravitational system | :class:`Vec2D` |
+----------------+------------------------------+-----------------------+
+| round_dance | dancing turtles rotating | compound shapes, clone|
+| | pairwise in opposite | shapesize, tilt, |
+| | direction | get_polyshape, update |
++----------------+------------------------------+-----------------------+
| tree | a (graphical) breadth | :func:`clone` |
| | first tree (using generators)| |
+----------------+------------------------------+-----------------------+
@@ -2204,6 +2357,32 @@ Changes since Python 2.6
This behaviour corresponds to a ``fill()`` call without arguments in
Python 2.6.
+Changes since Python 3.0
+========================
+
+- The methods :meth:`Turtle.shearfactor`, :meth:`Turtle.shapetransform` and
+ :meth:`Turtle.get_shapepoly` have been added. Thus the full range of
+ regular linear transforms is now available for transforming turtle shapes.
+ :meth:`Turtle.tiltangle` has been enhanced in functionality: it now can
+ be used to get or set the tiltangle. :meth:`Turtle.settiltangle` has been
+ deprecated.
+
+- The method :meth:`Screen.onkeypress` has been added as a complement to
+ :meth:`Screen.onkey` which in fact binds actions to the keyrelease event.
+ Accordingly the latter has got an alias: :meth:`Screen.onkeyrelease`.
+
+- The method :meth:`Screen.mainloop` has been added. So when working only
+ with Screen and Turtle objects one must not additonally import
+ :func:`mainloop` anymore.
+
+- Two input methods has been added :meth:`Screen.textinput` and
+ :meth:`Screen.numinput`. These popup input dialogs and return
+ strings and numbers respectively.
+
+- Two example scripts :file:`tdemo_nim.py` and :file:`tdemo_round_dance.py`
+ have been added to the Demo directory (source distribution only). As usual
+ they can be viewed and executed within the demo viewer :file:`turtleDemo.py`.
+
.. doctest::
:hide:
diff --git a/Lib/turtle.py b/Lib/turtle.py
index ded2b2712b..f0e4712565 100644
--- a/Lib/turtle.py
+++ b/Lib/turtle.py
@@ -1,8 +1,8 @@
#
# turtle.py: a Tkinter based turtle graphics module for Python
-# Version 1.0b1 - 31. 5. 2008
+# Version 1.1b - 4. 5. 2009
#
-# Copyright (C) 2006 - 2008 Gregor Lingl
+# Copyright (C) 2006 - 2009 Gregor Lingl
# email: glingl@aon.at
#
# This software is provided 'as-is', without any express or implied
@@ -100,7 +100,7 @@ extensions in in mind. These will be commented and documented elsewhere.
"""
-_ver = "turtle 1.0b1- - for Python 3.0 - 9. 6. 2008, 01:15"
+_ver = "turtle 1.1b- - for Python 3.1 - 4. 5. 2009"
# print(_ver)
@@ -112,36 +112,31 @@ import os
from os.path import isfile, split, join
from copy import deepcopy
-
-#from math import * ## for compatibility with old turtle module
+from tkinter import simpledialog
_tg_classes = ['ScrolledCanvas', 'TurtleScreen', 'Screen',
'RawTurtle', 'Turtle', 'RawPen', 'Pen', 'Shape', 'Vec2D']
_tg_screen_functions = ['addshape', 'bgcolor', 'bgpic', 'bye',
'clearscreen', 'colormode', 'delay', 'exitonclick', 'getcanvas',
- 'getshapes', 'listen', 'mode', 'onkey', 'onscreenclick', 'ontimer',
+ 'getshapes', 'listen', 'mainloop', 'mode', 'numinput',
+ 'onkey', 'onkeypress', 'onkeyrelease', 'onscreenclick', 'ontimer',
'register_shape', 'resetscreen', 'screensize', 'setup',
- 'setworldcoordinates', 'title', 'tracer', 'turtles', 'update',
+ 'setworldcoordinates', 'textinput', 'title', 'tracer', 'turtles', 'update',
'window_height', 'window_width']
_tg_turtle_functions = ['back', 'backward', 'begin_fill', 'begin_poly', 'bk',
'circle', 'clear', 'clearstamp', 'clearstamps', 'clone', 'color',
'degrees', 'distance', 'dot', 'down', 'end_fill', 'end_poly', 'fd',
- #'fill',
- 'fillcolor', 'forward', 'get_poly', 'getpen', 'getscreen',
+ 'fillcolor', 'forward', 'get_poly', 'getpen', 'getscreen', 'get_shapepoly',
'getturtle', 'goto', 'heading', 'hideturtle', 'home', 'ht', 'isdown',
'isvisible', 'left', 'lt', 'onclick', 'ondrag', 'onrelease', 'pd',
'pen', 'pencolor', 'pendown', 'pensize', 'penup', 'pos', 'position',
'pu', 'radians', 'right', 'reset', 'resizemode', 'rt',
'seth', 'setheading', 'setpos', 'setposition', 'settiltangle',
- 'setundobuffer', 'setx', 'sety', 'shape', 'shapesize', 'showturtle',
- 'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'towards', #'tracer',
+ 'setundobuffer', 'setx', 'sety', 'shape', 'shapesize', 'shapetransform', 'shearfactor', 'showturtle',
+ 'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'towards',
'turtlesize', 'undo', 'undobufferentries', 'up', 'width',
- #'window_height', 'window_width',
'write', 'xcor', 'ycor']
-_tg_utilities = ['write_docstringdict', 'done', 'mainloop']
-##_math_functions = ['acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh',
-## 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
-## 'log10', 'modf', 'pi', 'pow', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
+_tg_utilities = ['write_docstringdict', 'done']
__all__ = (_tg_classes + _tg_screen_functions + _tg_turtle_functions +
_tg_utilities) # + _math_functions)
@@ -172,16 +167,6 @@ _CFG = {"width" : 0.5, # Screen
"using_IDLE": False
}
-##print "cwd:", os.getcwd()
-##print "__file__:", __file__
-##
-##def show(dictionary):
-## print "=========================="
-## for key in sorted(dictionary.keys()):
-## print key, ":", dictionary[key]
-## print "=========================="
-## print
-
def config_dict(filename):
"""Convert content of config-file into dictionary."""
f = open(filename, "r")
@@ -230,7 +215,6 @@ def readconfig(cfgdict):
cfgdict2 = {}
if isfile(default_cfg):
cfgdict1 = config_dict(default_cfg)
- #print "1. Loading config-file %s from: %s" % (default_cfg, os.getcwd())
if "importconfig" in cfgdict1:
default_cfg = "turtle_%s.cfg" % cfgdict1["importconfig"]
try:
@@ -239,15 +223,9 @@ def readconfig(cfgdict):
except:
cfg_file2 = ""
if isfile(cfg_file2):
- #print "2. Loading config-file %s:" % cfg_file2
cfgdict2 = config_dict(cfg_file2)
-## show(_CFG)
-## show(cfgdict2)
_CFG.update(cfgdict2)
-## show(_CFG)
-## show(cfgdict1)
_CFG.update(cfgdict1)
-## show(_CFG)
try:
readconfig(_CFG)
@@ -697,7 +675,7 @@ class TurtleScreenBase(object):
fun(x, y)
self.cv.bind("<Button-%s>" % num, eventfun, add)
- def _onkey(self, fun, key):
+ def _onkeyrelease(self, fun, key):
"""Bind fun to key-release event of key.
Canvas must have focus. See method listen
"""
@@ -708,6 +686,24 @@ class TurtleScreenBase(object):
fun()
self.cv.bind("<KeyRelease-%s>" % key, eventfun)
+ def _onkeypress(self, fun, key=None):
+ """If key is given, bind fun to key-press event of key.
+ Otherwise bind fun to any key-press.
+ Canvas must have focus. See method listen.
+ """
+ if fun is None:
+ if key is None:
+ self.cv.unbind("<KeyPress>", None)
+ else:
+ self.cv.unbind("<KeyPress-%s>" % key, None)
+ else:
+ def eventfun(event):
+ fun()
+ if key is None:
+ self.cv.bind("<KeyPress>", eventfun)
+ else:
+ self.cv.bind("<KeyPress-%s>" % key, eventfun)
+
def _listen(self):
"""Set focus on canvas (in order to collect key-events)
"""
@@ -801,6 +797,57 @@ class TurtleScreenBase(object):
height = self.cv['height']
return width, height
+ def mainloop(self):
+ """Starts event loop - calling Tkinter's mainloop function.
+
+ No argument.
+
+ Must be last statement in a turtle graphics program.
+ Must NOT be used if a script is run from within IDLE in -n mode
+ (No subprocess) - for interactive use of turtle graphics.
+
+ Example (for a TurtleScreen instance named screen):
+ >>> screen.mainloop()
+
+ """
+ TK.mainloop()
+
+ def textinput(self, title, prompt):
+ """Pop up a dialog window for input of a string.
+
+ Arguments: title is the title of the dialog window,
+ prompt is a text mostly describing what information to input.
+
+ Return the string input
+ If the dialog is canceled, return None.
+
+ Example (for a TurtleScreen instance named screen):
+ >>> screen.textinput("NIM", "Name of first player:")
+
+ """
+ return simpledialog.askstring(title, prompt)
+
+ def numinput(self, title, prompt, default=None, minval=None, maxval=None):
+ """Pop up a dialog window for input of a number.
+
+ Arguments: title is the title of the dialog window,
+ prompt is a text mostly describing what numerical information to input.
+ default: default value
+ minval: minimum value for imput
+ maxval: maximum value for input
+
+ The number input must be in the range minval .. maxval if these are
+ given. If not, a hint is issued and the dialog remains open for
+ correction. Return the number input.
+ If the dialog is canceled, return None.
+
+ Example (for a TurtleScreen instance named screen):
+ >>> screen.numinput("Poker", "Your stakes:", 1000, minval=10, maxval=10000)
+
+ """
+ return simpledialog.askfloat(title, prompt, initialvalue=default,
+ minvalue=minval, maxvalue=maxval)
+
##############################################################################
### End of Tkinter - interface ###
@@ -913,7 +960,6 @@ class TurtleScreen(TurtleScreenBase):
upon components of the underlying graphics toolkit -
which is Tkinter in this case.
"""
-# _STANDARD_DELAY = 5
_RUNNING = True
def __init__(self, cv, mode=_CFG["mode"],
@@ -951,11 +997,11 @@ class TurtleScreen(TurtleScreenBase):
def clear(self):
"""Delete all drawings and all turtles from the TurtleScreen.
+ No argument.
+
Reset empty TurtleScreen to its initial state: white background,
no backgroundimage, no eventbindings and tracing on.
- No argument.
-
Example (for a TurtleScreen instance named screen):
screen.clear()
@@ -972,8 +1018,10 @@ class TurtleScreen(TurtleScreenBase):
self.bgcolor("white")
for btn in 1, 2, 3:
self.onclick(None, btn)
+ self.onkeypress(None)
for key in self._keys[:]:
self.onkey(None, key)
+ self.onkeypress(None, key)
Turtle._pen = None
def mode(self, mode=None):
@@ -1083,7 +1131,6 @@ class TurtleScreen(TurtleScreenBase):
shape = Shape("polygon", shape)
## else shape assumed to be Shape-instance
self._shapes[name] = shape
- # print "shape added:" , self._shapes
def _colorstr(self, color):
"""Return color string corresponding to args.
@@ -1243,9 +1290,12 @@ class TurtleScreen(TurtleScreenBase):
def update(self):
"""Perform a TurtleScreen update.
"""
+ tracing = self._tracing
+ self._tracing = True
for t in self.turtles():
t._update_data()
t._drawturtle()
+ self._tracing = tracing
self._update()
def window_width(self):
@@ -1336,10 +1386,44 @@ class TurtleScreen(TurtleScreenBase):
### consequently drawing a hexagon
"""
if fun == None:
- self._keys.remove(key)
+ if key in self._keys:
+ self._keys.remove(key)
elif key not in self._keys:
self._keys.append(key)
- self._onkey(fun, key)
+ self._onkeyrelease(fun, key)
+
+ def onkeypress(self, fun, key=None):
+ """Bind fun to key-press event of key if key is given,
+ or to any key-press-event if no key is given.
+
+ Arguments:
+ fun -- a function with no arguments
+ key -- a string: key (e.g. "a") or key-symbol (e.g. "space")
+
+ In order to be able to register key-events, TurtleScreen
+ must have focus. (See method listen.)
+
+ Example (for a TurtleScreen instance named screen
+ and a Turtle instance named turtle):
+
+ >>> def f():
+ fd(50)
+
+
+ >>> screen.onkey(f, "Up")
+ >>> screen.listen()
+
+ ### Subsequently the turtle can be moved by
+ ### repeatedly pressing the up-arrow key,
+ ### or by keeping pressed the up-arrow key.
+ ### consequently drawing a hexagon.
+ """
+ if fun == None:
+ if key in self._keys:
+ self._keys.remove(key)
+ elif key is not None and key not in self._keys:
+ self._keys.append(key)
+ self._onkeypress(fun, key)
def listen(self, xdummy=None, ydummy=None):
"""Set focus on TurtleScreen (in order to collect key-events)
@@ -1421,6 +1505,7 @@ class TurtleScreen(TurtleScreenBase):
resetscreen = reset
clearscreen = clear
addshape = register_shape
+ onkeyrelease = onkey
class TNavigator(object):
"""Navigation part of the RawTurtle.
@@ -1947,10 +2032,11 @@ class TPen(object):
self._fillcolor = fillcolor
self._drawing = True
self._speed = 3
- self._stretchfactor = (1, 1)
- self._tilt = 0
+ self._stretchfactor = (1., 1.)
+ self._shearfactor = 0.
+ self._tilt = 0.
+ self._shapetrafo = (1., 0., 0., 1.)
self._outlinewidth = 1
- ### self.screen = None # to override by child class
def resizemode(self, rmode=None):
"""Set resizemode to one of the values: "auto", "user", "noresize".
@@ -2262,6 +2348,7 @@ class TPen(object):
"speed" : number in range 0..10
"resizemode" : "auto" or "user" or "noresize"
"stretchfactor": (positive number, positive number)
+ "shearfactor": number
"outline" : positive number
"tilt" : number
@@ -2276,19 +2363,19 @@ class TPen(object):
>>> turtle.pen()
{'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1,
'pencolor': 'red', 'pendown': True, 'fillcolor': 'black',
- 'stretchfactor': (1,1), 'speed': 3}
+ 'stretchfactor': (1,1), 'speed': 3, 'shearfactor': 0.0}
>>> penstate=turtle.pen()
>>> turtle.color("yellow","")
>>> turtle.penup()
>>> turtle.pen()
{'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1,
'pencolor': 'yellow', 'pendown': False, 'fillcolor': '',
- 'stretchfactor': (1,1), 'speed': 3}
+ 'stretchfactor': (1,1), 'speed': 3, 'shearfactor': 0.0}
>>> p.pen(penstate, fillcolor="green")
>>> p.pen()
{'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1,
'pencolor': 'red', 'pendown': True, 'fillcolor': 'green',
- 'stretchfactor': (1,1), 'speed': 3}
+ 'stretchfactor': (1,1), 'speed': 3, 'shearfactor': 0.0}
"""
_pd = {"shown" : self._shown,
"pendown" : self._drawing,
@@ -2298,6 +2385,7 @@ class TPen(object):
"speed" : self._speed,
"resizemode" : self._resizemode,
"stretchfactor" : self._stretchfactor,
+ "shearfactor" : self._shearfactor,
"outline" : self._outlinewidth,
"tilt" : self._tilt
}
@@ -2351,12 +2439,20 @@ class TPen(object):
if isinstance(sf, (int, float)):
sf = (sf, sf)
self._stretchfactor = sf
+ if "shearfactor" in p:
+ self._shearfactor = p["shearfactor"]
if "outline" in p:
self._outlinewidth = p["outline"]
if "shown" in p:
self._shown = p["shown"]
if "tilt" in p:
self._tilt = p["tilt"]
+ if "stretchfactor" in p or "tilt" in p or "shearfactor" in p:
+ scx, scy = self._stretchfactor
+ shf = self._shearfactor
+ sa, ca = math.sin(self._tilt), math.cos(self._tilt)
+ self._shapetrafo = ( scx*ca, scy*(shf*ca + sa),
+ -scx*sa, scy*(ca - shf*sa))
self._update()
## three dummy methods to be implemented by child class:
@@ -2389,7 +2485,7 @@ class _TurtleImage(object):
self._setshape(shapeIndex)
def _setshape(self, shapeIndex):
- screen = self.screen # RawTurtle.screens[self.screenIndex]
+ screen = self.screen
self.shapeIndex = shapeIndex
if self._type == "polygon" == screen._shapes[shapeIndex]._type:
return
@@ -2699,9 +2795,11 @@ class RawTurtle(TPen, TNavigator):
>>> turtle.shapesize(5, 5, 12)
>>> turtle.shapesize(outline=8)
"""
- if stretch_wid is None and stretch_len is None and outline == None:
+ if stretch_wid is stretch_len is outline == None:
stretch_wid, stretch_len = self._stretchfactor
return stretch_wid, stretch_len, self._outlinewidth
+ if stretch_wid == 0 or stretch_len == 0:
+ raise TurtleGraphicsError("stretch_wid/stretch_len must not be zero")
if stretch_wid is not None:
if stretch_len is None:
stretchfactor = stretch_wid, stretch_wid
@@ -2716,11 +2814,33 @@ class RawTurtle(TPen, TNavigator):
self.pen(resizemode="user",
stretchfactor=stretchfactor, outline=outline)
+ def shearfactor(self, shear=None):
+ """Set or return the current shearfactor.
+
+ Optional argument: shear -- number, tangent of the shear angle
+
+ Shear the turtleshape according to the given shearfactor shear,
+ which is the tangent of the shear angle. DO NOT change the
+ turtle's heading (direction of movement).
+ If shear is not given: return the current shearfactor, i. e. the
+ tangent of the shear angle, by which lines parallel to the
+ heading of the turtle are sheared.
+
+ Examples (for a Turtle instance named turtle):
+ >>> turtle.shape("circle")
+ >>> turtle.shapesize(5,2)
+ >>> turtle.shearfactor(0.5)
+ >>> turtle.shearfactor()
+ >>> 0.5
+ """
+ if shear is None:
+ return self._shearfactor
+ self.pen(resizemode="user", shearfactor=shear)
+
def settiltangle(self, angle):
"""Rotate the turtleshape to point in the specified direction
- Optional argument:
- angle -- number
+ Argument: angle -- number
Rotate the turtleshape to point in the direction specified by angle,
regardless of its current tilt-angle. DO NOT change the turtle's
@@ -2741,14 +2861,19 @@ class RawTurtle(TPen, TNavigator):
tilt = (tilt * math.pi / 180.0) % (2*math.pi)
self.pen(resizemode="user", tilt=tilt)
- def tiltangle(self):
- """Return the current tilt-angle.
+ def tiltangle(self, angle=None):
+ """Set or return the current tilt-angle.
- No argument.
+ Optional argument: angle -- number
+
+ Rotate the turtleshape to point in the direction specified by angle,
+ regardless of its current tilt-angle. DO NOT change the turtle's
+ heading (direction of movement).
+ If angle is not given: return the current tilt-angle, i. e. the angle
+ between the orientation of the turtleshape and the heading of the
+ turtle (its direction of movement).
- Return the current tilt-angle, i. e. the angle between the
- orientation of the turtleshape and the heading of the turtle
- (its direction of movement).
+ Deprecated since Python 3.1
Examples (for a Turtle instance named turtle):
>>> turtle.shape("circle")
@@ -2757,8 +2882,11 @@ class RawTurtle(TPen, TNavigator):
>>> turtle.tiltangle()
>>>
"""
- tilt = -self._tilt * (180.0/math.pi) * self._angleOrient
- return (tilt / self._degreesPerAU) % self._fullcircle
+ if angle is None:
+ tilt = -self._tilt * (180.0/math.pi) * self._angleOrient
+ return (tilt / self._degreesPerAU) % self._fullcircle
+ else:
+ self.settiltangle(angle)
def tilt(self, angle):
"""Rotate the turtleshape by angle.
@@ -2779,6 +2907,46 @@ class RawTurtle(TPen, TNavigator):
"""
self.settiltangle(angle + self.tiltangle())
+ def shapetransform(self, t11=None, t12=None, t21=None, t22=None):
+ """Set or return the current transformation matrix of the turtle shape.
+
+ Optional arguments: t11, t12, t21, t22 -- numbers.
+
+ If none of the matrix elements are given, return the transformation
+ matrix.
+ Otherwise set the given elements and transform the turtleshape
+ according to the matrix consisting of first row t11, t12 and
+ second row t21, 22.
+ Modify stretchfactor, shearfactor and tiltangle according to the
+ given matrix.
+
+ Examples (for a Turtle instance named turtle):
+ >>> turtle.shape("square")
+ >>> turtle.shapesize(4,2)
+ >>> turtle.shearfactor(-0.5)
+ >>> turtle.shapetransform()
+ >>> (4.0, -1.0, -0.0, 2.0)
+ """
+ if t11 is t12 is t21 is t22 is None:
+ return self._shapetrafo
+ m11, m12, m21, m22 = self._shapetrafo
+ if t11 is not None: m11 = t11
+ if t12 is not None: m12 = t12
+ if t21 is not None: m21 = t21
+ if t22 is not None: m22 = t22
+ if t11 * t22 - t12 * t21 == 0:
+ raise TurtleGraphicsError("Bad shape transform matrix: must not be singular")
+ self._shapetrafo = (m11, m12, m21, m22)
+ alfa = math.atan2(-m21, m11) % (2 * math.pi)
+ sa, ca = math.sin(alfa), math.cos(alfa)
+ a11, a12, a21, a22 = (ca*m11 - sa*m21, ca*m12 - sa*m22,
+ sa*m11 + ca*m21, sa*m12 + ca*m22)
+ self._stretchfactor = a11, a22
+ self._shearfactor = a12/a22
+ self._tilt = alfa
+ self._update()
+
+
def _polytrafo(self, poly):
"""Computes transformed polygon shapes from a shape
according to current position and heading.
@@ -2791,6 +2959,36 @@ class RawTurtle(TPen, TNavigator):
return [(p0+(e1*x+e0*y)/screen.xscale, p1+(-e0*x+e1*y)/screen.yscale)
for (x, y) in poly]
+ def get_shapepoly(self):
+ """Return the current shape polygon as tuple of coordinate pairs.
+
+ No argument.
+
+ Examples (for a Turtle instance named turtle):
+ >>> turtle.shape("square")
+ >>> turtle.shapetransform(4, -1, 0, 2)
+ >>> turtle.get_shapepoly()
+ ((50, -20), (30, 20), (-50, 20), (-30, -20))
+
+ """
+ shape = self.screen._shapes[self.turtle.shapeIndex]
+ if shape._type == "polygon":
+ return self._getshapepoly(shape._data, shape._type == "compound")
+ # else return None
+
+ def _getshapepoly(self, polygon, compound=False):
+ """Calculate transformed shape polygon according to resizemode
+ and shapetransform.
+ """
+ if self._resizemode == "user" or compound:
+ t11, t12, t21, t22 = self._shapetrafo
+ elif self._resizemode == "auto":
+ l = max(1, self._pensize/5.0)
+ t11, t12, t21, t22 = l, 0, 0, l
+ elif self._resizemode == "noresize":
+ return polygon
+ return tuple([(t11*x + t12*y, t21*x + t22*y) for (x, y) in polygon])
+
def _drawturtle(self):
"""Manages the correct rendering of the turtle with respect to
its shape, resizemode, stretch and tilt etc."""
@@ -2802,35 +3000,20 @@ class RawTurtle(TPen, TNavigator):
self._hidden_from_screen = False
tshape = shape._data
if ttype == "polygon":
- if self._resizemode == "noresize":
- w = 1
- shape = tshape
- else:
- if self._resizemode == "auto":
- lx = ly = max(1, self._pensize/5.0)
- w = self._pensize
- tiltangle = 0
- elif self._resizemode == "user":
- lx, ly = self._stretchfactor
- w = self._outlinewidth
- tiltangle = self._tilt
- shape = [(lx*x, ly*y) for (x, y) in tshape]
- t0, t1 = math.sin(tiltangle), math.cos(tiltangle)
- shape = [(t1*x+t0*y, -t0*x+t1*y) for (x, y) in shape]
- shape = self._polytrafo(shape)
+ if self._resizemode == "noresize": w = 1
+ elif self._resizemode == "auto": w = self._pensize
+ else: w =self._outlinewidth
+ shape = self._polytrafo(self._getshapepoly(tshape))
fc, oc = self._fillcolor, self._pencolor
screen._drawpoly(titem, shape, fill=fc, outline=oc,
width=w, top=True)
elif ttype == "image":
screen._drawimage(titem, self._position, tshape)
elif ttype == "compound":
- lx, ly = self._stretchfactor
- w = self._outlinewidth
for item, (poly, fc, oc) in zip(titem, tshape):
- poly = [(lx*x, ly*y) for (x, y) in poly]
- poly = self._polytrafo(poly)
+ poly = self._polytrafo(self._getshapepoly(poly, True))
screen._drawpoly(item, poly, fill=self._cc(fc),
- outline=self._cc(oc), width=w, top=True)
+ outline=self._cc(oc), width=self._outlinewidth, top=True)
else:
if self._hidden_from_screen:
return
@@ -2867,22 +3050,10 @@ class RawTurtle(TPen, TNavigator):
tshape = shape._data
if ttype == "polygon":
stitem = screen._createpoly()
- if self._resizemode == "noresize":
- w = 1
- shape = tshape
- else:
- if self._resizemode == "auto":
- lx = ly = max(1, self._pensize/5.0)
- w = self._pensize
- tiltangle = 0
- elif self._resizemode == "user":
- lx, ly = self._stretchfactor
- w = self._outlinewidth
- tiltangle = self._tilt
- shape = [(lx*x, ly*y) for (x, y) in tshape]
- t0, t1 = math.sin(tiltangle), math.cos(tiltangle)
- shape = [(t1*x+t0*y, -t0*x+t1*y) for (x, y) in shape]
- shape = self._polytrafo(shape)
+ if self._resizemode == "noresize": w = 1
+ elif self._resizemode == "auto": w = self._pensize
+ else: w =self._outlinewidth
+ shape = self._polytrafo(self._getshapepoly(tshape))
fc, oc = self._fillcolor, self._pencolor
screen._drawpoly(stitem, shape, fill=fc, outline=oc,
width=w, top=True)
@@ -2895,13 +3066,10 @@ class RawTurtle(TPen, TNavigator):
item = screen._createpoly()
stitem.append(item)
stitem = tuple(stitem)
- lx, ly = self._stretchfactor
- w = self._outlinewidth
for item, (poly, fc, oc) in zip(stitem, tshape):
- poly = [(lx*x, ly*y) for (x, y) in poly]
- poly = self._polytrafo(poly)
+ poly = self._polytrafo(self._getshapepoly(poly, True))
screen._drawpoly(item, poly, fill=self._cc(fc),
- outline=self._cc(oc), width=w, top=True)
+ outline=self._cc(oc), width=self._outlinewidth, top=True)
self.stampItems.append(stitem)
self.undobuffer.push(("stamp", stitem))
return stitem
@@ -3137,57 +3305,6 @@ class RawTurtle(TPen, TNavigator):
"""
return isinstance(self._fillpath, list)
-## def fill(self, flag=None):
-## """Call fill(True) before drawing a shape to fill, fill(False) when done.
-##
-## Optional argument:
-## flag -- True/False (or 1/0 respectively)
-##
-## Call fill(True) before drawing the shape you want to fill,
-## and fill(False) when done.
-## When used without argument: return fillstate (True if filling,
-## False else)
-##
-## Example (for a Turtle instance named turtle):
-## >>> turtle.fill(True)
-## >>> turtle.forward(100)
-## >>> turtle.left(90)
-## >>> turtle.forward(100)
-## >>> turtle.left(90)
-## >>> turtle.forward(100)
-## >>> turtle.left(90)
-## >>> turtle.forward(100)
-## >>> turtle.fill(False)
-## """
-## filling = isinstance(self._fillpath, list)
-## if flag is None:
-## return filling
-## screen = self.screen
-## entry1 = entry2 = ()
-## if filling:
-## if len(self._fillpath) > 2:
-## self.screen._drawpoly(self._fillitem, self._fillpath,
-## fill=self._fillcolor)
-## entry1 = ("dofill", self._fillitem)
-## if flag:
-## self._fillitem = self.screen._createpoly()
-## self.items.append(self._fillitem)
-## self._fillpath = [self._position]
-## entry2 = ("beginfill", self._fillitem) # , self._fillpath)
-## self._newLine()
-## else:
-## self._fillitem = self._fillpath = None
-## if self.undobuffer:
-## if entry1 == ():
-## if entry2 != ():
-## self.undobuffer.push(entry2)
-## else:
-## if entry2 == ():
-## self.undobuffer.push(entry1)
-## else:
-## self.undobuffer.push(["seq", entry1, entry2])
-## self._update()
-
def begin_fill(self):
"""Called just before drawing a shape to be filled.
@@ -3243,7 +3360,6 @@ class RawTurtle(TPen, TNavigator):
>>> turtle.dot()
>>> turtle.fd(50); turtle.dot(20, "blue"); turtle.fd(50)
"""
- #print "dot-1:", size, color
if not color:
if isinstance(size, (str, tuple)):
color = self._colorstr(size)
@@ -3256,10 +3372,8 @@ class RawTurtle(TPen, TNavigator):
if size is None:
size = self._pensize + max(self._pensize, 4)
color = self._colorstr(color)
- #print "dot-2:", size, color
if hasattr(self.screen, "_dot"):
item = self.screen._dot(self._position, size, color)
- #print "dot:", size, color, "item:", item
self.items.append(item)
if self.undobuffer:
self.undobuffer.push(("dot", item))
@@ -3355,7 +3469,7 @@ class RawTurtle(TPen, TNavigator):
>>> p = turtle.get_poly()
>>> turtle.register_shape("myFavouriteShape", p)
"""
- ## check if there is any poly? -- 1st solution:
+ ## check if there is any poly?
if self._poly is not None:
return tuple(self._poly)
@@ -3399,35 +3513,11 @@ class RawTurtle(TPen, TNavigator):
### screen oriented methods recurring to methods of TurtleScreen
################################################################
-## def window_width(self):
-## """ Returns the width of the turtle window.
-##
-## No argument.
-##
-## Example (for a TurtleScreen instance named screen):
-## >>> screen.window_width()
-## 640
-## """
-## return self.screen._window_size()[0]
-##
-## def window_height(self):
-## """ Return the height of the turtle window.
-##
-## No argument.
-##
-## Example (for a TurtleScreen instance named screen):
-## >>> screen.window_height()
-## 480
-## """
-## return self.screen._window_size()[1]
-
def _delay(self, delay=None):
"""Set delay value which determines speed of turtle animation.
"""
return self.screen.delay(delay)
- ##### event binding methods #####
-
def onclick(self, fun, btn=1, add=None):
"""Bind fun to mouse-click event on this turtle on canvas.
@@ -3593,8 +3683,8 @@ class _Screen(TurtleScreen):
topbottom = _CFG["topbottom"]
self._root.setupcanvas(width, height, canvwidth, canvheight)
_Screen._canvas = self._root._getcanvas()
- self.setup(width, height, leftright, topbottom)
TurtleScreen.__init__(self, _Screen._canvas)
+ self.setup(width, height, leftright, topbottom)
def setup(self, width=_CFG["width"], height=_CFG["height"],
startx=_CFG["leftright"], starty=_CFG["topbottom"]):
@@ -3634,6 +3724,7 @@ class _Screen(TurtleScreen):
if starty is None:
starty = (sh - height) / 2
self._root.set_geometry(width, height, startx, starty)
+ self.update()
def title(self, titlestring):
"""Set title of turtle-window
@@ -3803,16 +3894,8 @@ def getmethparlist(ob):
argText1 = argText2 = ""
# bit of a hack for methods - turn it into a function
# but we drop the "self" param.
-## if type(ob)==types.MethodType:
-## fob = ob.im_func
-## argOffset = 1
-## else:
-## fob = ob
-## argOffset = 0
# Try and build one for Python defined functions
argOffset = 1
-## if type(fob) in [types.FunctionType, types.LambdaType]:
-## try:
counter = ob.__code__.co_argcount
items2 = list(ob.__code__.co_varnames[argOffset:counter])
realArgs = ob.__code__.co_varnames[argOffset:counter]
@@ -3831,8 +3914,6 @@ def getmethparlist(ob):
argText1 = "(%s)" % argText1
argText2 = ", ".join(items2)
argText2 = "(%s)" % argText2
-## except:
-## pass
return argText1, argText2
def _turtle_docrevise(docstr):
@@ -3871,7 +3952,6 @@ for methodname in _tg_screen_functions:
continue
defstr = ("def %(key)s%(pl1)s: return _getscreen().%(key)s%(pl2)s" %
{'key':methodname, 'pl1':pl1, 'pl2':pl2})
-## print("Screen:", defstr)
exec(defstr)
eval(methodname).__doc__ = _screen_docrevise(eval('_Screen.'+methodname).__doc__)
@@ -3882,13 +3962,11 @@ for methodname in _tg_turtle_functions:
continue
defstr = ("def %(key)s%(pl1)s: return _getpen().%(key)s%(pl2)s" %
{'key':methodname, 'pl1':pl1, 'pl2':pl2})
-## print("Turtle:", defstr)
exec(defstr)
eval(methodname).__doc__ = _turtle_docrevise(eval('Turtle.'+methodname).__doc__)
-done = mainloop = TK.mainloop
-#del pl1, pl2, defstr
+done = mainloop
if __name__ == "__main__":
def switchpen():
diff --git a/Misc/NEWS b/Misc/NEWS
index 2e4c6bd84c..5b4f0ab482 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -118,6 +118,9 @@ Installation
Library
-------
+- Issue #5923: Update the ``turtle`` module to version 1.1, add two new
+ turtle demos in Demo/turtle.
+
- Issue #5692: In :class:`zipfile.Zipfile`, fix wrong path calculation when
extracting a file to the root directory.