Module pgl

The pgl module implements the Portable Graphics Library (pgl) on top of Tkinter, which is the most common graphics package for use with Python.

Expand source code
# File: pgl.py

"""
The pgl module implements the Portable Graphics Library (pgl) on top of
Tkinter, which is the most common graphics package for use with Python.
"""

import atexit
import inspect
import math
import sys
import time

# Version information

PGL_VERSION = 0.89
PGL_DATE = "18-Feb-20"

# Conditional imports

try:
    import tkinter
    try:
        import tkinter.font as tkFont
    except Exception:
        import tkFont
except Exception as e:
    print('Could not load tkinter: ' + str(e))

try:
    from PIL import ImageTk, Image
    _imageModel = "PIL"
except Exception:
    _imageModel = "PhotoImage"

spyderFlag = False

try:
    import spydercustomize as customize
    spyderFlag = True
except Exception:
    try:
        import sitecustomize as customize
        spyderFlag = True
    except Exception:
        pass

if spyderFlag:
    try:
        sys_clear_post_mortem = customize.clear_post_mortem
        def patched_clear_post_mortem():
            customize.clear_post_mortem = sys_clear_post_mortem
            try:
                if tkinter._root is not None:
                    tkinter._root.mainloop()
            except Exception:
                pass
            sys_clear_post_mortem()
        customize.clear_post_mortem = patched_clear_post_mortem
    except Exception:
        pass

# Class GWindow

class GWindow(object):
    """
    This class represents a graphics window that can contain graphical
    objects.
    """

# Public constants

    DEFAULT_WIDTH = 500
    DEFAULT_HEIGHT = 300
    MIN_WAKEUP = 20

# Constructor: GWindow

    def __init__(self, width=DEFAULT_WIDTH, height=DEFAULT_HEIGHT):
        """
        The constructor takes either of the following forms:

        <pre>
           GWindow()
           GWindow(width, height)
        </pre>

        If the dimensions are missing, the constructor creates a
        <code>GWindow</code> with a default size.
        """
        try:
            tk = tkinter._root
            tk.deiconify()
        except AttributeError:
            tk = tkinter.Tk()
            tkinter._root = tk
        self.windowWidth = width
        self.windowHeight = height
        self.tk = tk
        self.tk.protocol("WM_DELETE_WINDOW", self.deleteWindow)
        for w in tk.winfo_children():
            w.destroy()
        self.canvas = tkinter.Canvas(tk, width=width, height=height,
                                     highlightthickness=0)
        try:
            self.canvas.pack()
        except:
            pass
        if spyderFlag:
            def cancelTopmost():
                tk.attributes("-topmost", False)
            tk.attributes("-topmost", True)
            tk.focus_force()
            self.canvas.after(0, cancelTopmost)
        self.canvas.update()
        self.images = { }
        self.timers = [ ]
        self.base = GCompound()
        self.base.gw = self
        self.eventManager = EventManager(self)
        self.setWindowTitle(getProgramName())
        self.eventLoopStarted = False
        self.active = True
        if not spyderFlag:
            atexit.register(self.startEventLoop)

    def __eq__(self, other):
        if type(other) is GWindow:
            return self.canvas is other.canvas
        return False

# Public method: close

    def close(self):
        """
        Deletes the window from the screen.
        """
        self.deleteWindow()

# Public method: eventLoop

    def eventLoop(self):
        """
        Waits for events to happen in the window.
        """
        self.eventLoopStarted = True
        tkinter._root.mainloop()

# Public method: requestFocus

    def requestFocus(self):
        """
        Asks the system to assign the keyboard focus to the window, which
        brings it to the top and ensures that key events are delivered to
        the window.
        """
        tkinter._root.canvas.focus_set()

# Public method: clear

    def clear(self):
        """
        Clears the contents of the window.
        """
        self.base.removeAll()

# Public method: getWidth

    def getWidth(self):
        """
        Returns the width of the graphics window in pixels.
        """
        return self.windowWidth

# Public method: getHeight

    def getHeight(self):
        """
        Returns the height of the graphics window in pixels.
        """
        return self.windowHeight

# Public method: addEventListener

    def addEventListener(self, type, fn):
        """
        Adds an event listener of the specified type to the window.
        """
        self.eventManager.addEventListener(type, fn)

# Public method: repaint

    def repaint(self):
        """
        Schedule a repaint on this window.
        """
        pass

# Public method: setWindowTitle

    def setWindowTitle(self, title):
        """
        Sets the title of the graphics window.
        """
        self.windowTitle = title
        self.tk.title(title)

# Public method: getWindowTitle

    def getWindowTitle(self):
        """
        Returns the title of the graphics window.
        """
        return self.windowTitle

# Public method: add

    def add(self, gobj, x=None, y=None):
        """
        Adds the <code>GObject</code> to the window.  The first parameter
        is the object to be added.  The <code>x</code> and <code>y</code>
        parameters are optional.  If they are supplied, the location of
        the object is set to (<code>x</code>, <code>y</code>).
        """
        self.base.add(gobj, x, y)

# Public method: remove

    def remove(self, gobj):
        """
        Removes the object from the window.
        """
        self.base.remove(gobj)

# Public method: getElementAt

    def getElementAt(self, x, y):
        """
        Returns the topmost <code>GObject</code> containing the
        point (x, y), or <code>None</code> if no such object exists.
        """
        return self.base.getElementAt(x, y)

# Public method: createTimer

    def createTimer(self, fn, delay):
        """
        Creates a new timer object that calls fn after the specified
        delay, which is measured in milliseconds.  The timer must be
        started by calling the <code>start</code> method.
        """
        return GTimer(self, fn, delay)

# Public method: setTimeout

    def setTimeout(self, fn, delay):
        """
        Creates and starts a one-shot timer that calls fn after the
        specified delay, which is measured in milliseconds.  The
        setTimeout method returns the <code>GTimer</code> object.
        """
        timer = GTimer(self, fn, delay)
        timer.start()
        return timer

# Public method: setInterval

    def setInterval(self, fn, delay):
        """
        Creates and starts an interval timer that calls fn after the
        specified delay, which is measured in milliseconds.  The
        setInterval method returns the <code>GTimer</code> object.
        """
        timer = GTimer(self, fn, delay)
        timer.setRepeats(True)
        timer.start()
        return timer

# Public method: pause

    def pause(self, delay):
        """
        Pauses the current thread for the specified delay, which is
        measured in milliseconds.  The pause method periodically checks
        the event queue to update the contents of the window.
        """
        nCycles = delay // GWindow.MIN_WAKEUP
        for i in range(nCycles):
            self.tk.update_idletasks()
            self.tk.update()
            time.sleep(delay / nCycles / 1000)

# Private method: deleteWindow

    def deleteWindow(self):
        """
        Closes the window and exits from the event loop.
        """
        self.active = False
        for timer in self.timers:
            timer.stop()
        tkinter._root.destroy()
        del tkinter._root

# Private method: startEventLoop

    def startEventLoop(self):
        """
        Starts the event loop if it wasn't run explicitly.
        """
        if not self.eventLoopStarted:
            self.eventLoop()

# Private method: _rebuild

    def _rebuild(self):
        """
        Rebuilds the tkinter data structure for the window.  This
        operation is triggered if a global update is necessary.
        """
        self.canvas.delete("all")
        self.base._install(self, SimpleTransform())

# Class: GObject

class GObject(object):
    """
    This class is the common superclass of all graphical objects that can
    be displayed on a graphical window. For examples illustrating the use
    of the <code>GObject</code> class, see the descriptions of the
    individual subclasses.
    """

# Constructor: GObject

    def __init__(self):
        """
        Creates a new <code>GObject</code>.  The constructor is called
        only by subclasses.
        """
        self.x = 0.0
        self.y = 0.0
        self.sf = 1
        self.angle = 0
        self.color = "Black"
        self.lineWidth = 1.0
        self.visible = True
        self.parent = None
        self.tkid = None
        self.gw = None

# Public method: getX

    def getX(self):
        """
        Returns the x-coordinate of the object.
        """
        return self.x

# Public method: getY

    def getY(self):
        """
        Returns the y-coordinate of the object.
        """
        return self.y

# Public method: getLocation

    def getLocation(self):
        """
        Returns the location of this object as a <code>GPoint</code>.
        """
        return GPoint(self.x, self.y)

# Public method: setLocation

    def setLocation(self, x, y):
        """
        Sets the location of this object to the specified point.
        """
        if type(x) is GPoint:
            x, y = x.getX(), x.getY()
        elif type(x) is dict:
            x, y = x.x, x.y
        self.x = x
        self.y = y
        self._updateLocation()

# Public method: move

    def move(self, dx, dy):
        """
        Moves the object on the screen using the displacements
        <code>dx</code> and <code>dy</code>.
        """
        self.setLocation(self.x + dx, self.y + dy)

# Public method: movePolar

    def movePolar(self, r, theta):
        """
        Moves the object on the screen the distance <i>r</i> in the
        direction <i>theta</i>.
        """
        dx = r * math.cos(math.radians(theta))
        dy = -r * math.sin(math.radians(theta))
        self.move(dx, dy)

# Public method: getWidth

    def getWidth(self):
        """
        Returns the width of this object, which is defined to be the width of
        the bounding box.
        """
        return self.getBounds().getWidth()

# Public method: getHeight

    def getHeight(self):
        """
        Returns the height of this object, which is defined to be the height
        of the bounding box.
        """
        return self.getBounds().getHeight()

# Public method: getSize

    def getSize(self):
        """
        Returns the size of the object as a <code>GDimension</code>.
        """
        bounds = self.getBounds()
        return GDimension(bounds.getWidth(), bounds.getHeight())

# Public method: setLineWidth

    def setLineWidth(self, lineWidth):
        """
        Sets the width of the line used to draw this object.
        """
        self.lineWidth = lineWidth
        self.updateProperties(width=lineWidth)

# Public method: getLineWidth

    def getLineWidth(self):
        """
        Returns the width of the line used to draw this object.
        """
        return self.lineWidth

# Public method: setColour

    def setColour(self, color):
        """
        Alternate spelling for <code>setColor</code>.
        """
        self.setColor(color)

# Public method: setColor

    def setColor(self, color):
        """
        Sets the color used to display this object.  The color parameter is
        usually one of the CSS color names.  The color can also be specified
        as a string in the form <code>"#rrggbb"</code> where <code>rr</code>,
        <code>gg</code>, and <code>bb</code> are pairs of hexadecimal digits
        indicating the red, green, and blue components of the color.
        """
        rgb = convertColorToRGB(color)
        self.color = convertRGBToColor(rgb)
        self.updateColor()

# Public method: getColour

    def getColour(self):
        """
        Alternate spelling for <code>getColor</code>.
        """
        return self.getColor()

# Public method: getColor

    def getColor(self):
        """
        Returns the current color as a string in the form
        <code>"#rrggbb"</code>.  In this string, the values <code>rr</code>,
        <code>gg</code>, and <code>bb</code> are two-digit hexadecimal
        values representing the red, green, and blue components.
        """
        return self.color

# Public method: scale

    def scale(self, sf):
        """
        Scales the object by the specified scale factor.
        """
        raise Exception("Not yet implemented")

# Public method: rotate

    def rotate(self, theta):
        """
        Transforms the object by rotating it theta degrees counterclockwise
        around its origin.
        """
        raise Exception("Not yet implemented")

# Public method: setVisible

    def setVisible(self, flag):
        """
        Sets whether this object is visible.
        """
        self.visible = flag
        self.updateVisible()

# Public method: isVisible

    def isVisible(self):
        """
        Returns true if this object is visible.
        """
        return self.visible

# Public method: sendForward

    def sendForward(self):
        """
        Moves this object one step toward the front in the z dimension.
        If it was already at the front of the stack, nothing happens.
        """
        parent = self.getParent()
        if parent is not None:
            parent._sendForward(self)

# Public method: sendToFront

    def sendToFront(self):
        """
        Moves this object to the front of the display in the z dimension.
        By moving it to the front, this object will appear to be on top of the
        other graphical objects on the display and may hide any objects that
        are further back.
        """
        parent = self.getParent()
        if parent is not None:
            parent._sendToFront(self)

# Public method: sendBackward

    def sendBackward(self):
        """
        Moves this object one step toward the back in the z dimension.
        If it was already at the back of the stack, nothing happens.
        """
        parent = self.getParent()
        if parent is not None:
            parent._sendBackward(self)

# Public method: sendToBack

    def sendToBack(self):
        """
        Moves this object to the back of the display in the z dimension.
        By moving it to the back, this object will appear to be behind
        the other graphical objects on the display and may be obscured
        by other objects in front.
        """
        parent = self.getParent()
        if parent is not None:
            parent._sendToBack(self)

# Public method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        if type(x) is GPoint:
            x, y = x.getX(), x.getY()
        elif type(x) is dict:
            x, y = x.x, x.y
        bounds = self.getBounds()
        if bounds is None:
            return False
        return bounds.contains(x, y)

# Public method: getParent

    def getParent(self):
        """
        Returns a pointer to the <code>GCompound</code> that contains this
        object.  Every <code>GWindow</code> is initialized to contain a
        single <code>GCompound</code> that is aligned with the window.
        Adding objects to the window adds them to that <code>GCompound</code>,
        which means that every object you add to the window has a parent.
        Calling <code>getParent</code> on the top-level <code>GCompound</code>
        returns <code>None</code>.
        """
        return self.parent

# Abstract method: getType

    def getType(self):
        """
        Returns the concrete type of the object as a string, as in
        "GOval" or "GRect".
        """
        raise Exception("getType is not defined in the GObject class")

# Abstract method: getBounds

    def getBounds(self):
        """
        Returns the bounding box of this object, which is defined to be the
        smallest rectangle that covers everything drawn by the figure.  The
        coordinates of this rectangle do not necessarily match the location
        returned by <code>getLocation</code>.  Given a <code>GLabel</code>
        object, for example, <code>getLocation</code> returns the
        coordinates of the point on the baseline at which the string begins.
        The <code>getBounds</code> method, by contrast, returns a rectangle
        that covers the entire window area occupied by the string.
        """
        raise Exception("getBounds is not defined in the GObject class")

# Private method: updateProperties

    def updateProperties(self, **options):
        """
        Updates the specified properties of the object, if it is installed
        in a window.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        tkc.itemconfig(self.tkid, **options)

# Private method: _updateLocation

    def _updateLocation(self):
        """
        Updates the location for this object from the stored x and y
        values.  Some subclasses need to override this method.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        offx = 0
        offy = 0
        gobj = self.getParent()
        while gobj is not None:
            offx += gobj.x
            offy += gobj.y
            gobj = gobj.getParent()
        dx = (self.x + offx) - coords[0]
        dy = (self.y + offy) - coords[1]
        tkc.move(self.tkid, dx, dy)

# Private method: updateColor

    def updateColor(self):
        """
        Updates the color properties.  Some subclasses need to override
        this method.
        """
        self.updateProperties(fill=self.color)

# Private method: updateVisible

    def updateVisible(self):
        """
        Updates the visible property.
        """
        if self.visible:
            self.updateProperties(state=tkinter.NORMAL)
        else:
            self.updateProperties(state=tkinter.HIDDEN)

# Private method: getWindow

    def getWindow(self):
        """
        Returns the <code>GWindow</code> in which this <code>GObject</code>
        is installed.  If the object is not installed in a window, this
        method returns <code>None</code>.
        """
        gobj = self
        while (gobj.parent is not None):
            gobj = gobj.parent
        return gobj.gw

# Private abstract method: _install

    def _install(self, target, ctm):
        """
        Installs the object in the target, creating any tkinter objects
        that are necessary.
        """
        raise Exception("_install is not defined in the GObject class")

# Class: GFillableObject

class GFillableObject(GObject):
    """
    This abstract class is the superclass of all objects that are fillable.
    """

# Constructor: GFillableObject

    def __init__(self):
        """
        Initializes a <code>GFillableObject</code>.  Because this is an
        abstract class, clients should not call this constructor explicitly.
        """
        GObject.__init__(self)
        self.fillFlag = False
        self.fillColor = ""

# Public method: setFilled

    def setFilled(self, flag):
        """
        Sets the fill status for the object, where <code>False</code>
        is outlined and <code>True</code> is filled.
        """
        self.fillFlag = flag
        self.updateColor()

# Public method: isFilled

    def isFilled(self):
        """
        Returns <code>True</code> if the object is filled.
        """
        return self.fillFlag

# Public method: setFillColor

    def setFillColor(self, color):
        """
        Sets the color used to display the filled region of the object.
        """
        rgb = convertColorToRGB(color)
        self.fillColor = convertRGBToColor(rgb)
        self.updateColor()

# Public method: getFillColor

    def getFillColor(self):
        """
        Returns the color used to display the filled region of this
        object.  If no fill color has been set, <code>getFillColor</code>
        returns the empty string.
        """
        return self.fillColor

# Override method: updateColor

    def updateColor(self):
        """
        Updates the color properties for a <code>GFillableObject</code>.
        """
        outline = self.color
        if self.fillFlag:
            fill = self.fillColor
            if fill is None or fill == "":
                fill = outline
        else:
            fill = ""
        self.updateProperties(outline=outline, fill=fill)

# Class: GRect

class GRect(GFillableObject):
    """
    This class represents a graphical object whose appearance consists of
    a rectangular box.
    """

# Constructor: GRect

    def __init__(self, a1, a2, a3=None, a4=None):
        """
        The <code>GRect</code> constructor takes either of the following
        forms:

        <pre>
           GRect(width, height)
           GRect(x, y, width, height)
        </pre>

        If the <code>x</code> and <code>y</code> parameters are missing,
        the origin is set to (0, 0).
        """
        GFillableObject.__init__(self)
        if a3 is None:
            x = 0
            y = 0
            width = a1
            height = a2
        else:
            x = a1
            y = a2
            width = a3
            height = a4
        self.width = width
        self.height = height
        self.setLocation(x, y)

# Public method: setSize

    def setSize(self, width, height=None):
        """
        Changes the size of this rectangle as specified.
        """
        if type(width) is GDimension:
            width, height = width.getWidth(), width.getHeight()
        self.width = width
        self.height = height
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        tkc.coords(self.tkid, coords[0], coords[1],
                   coords[0] + width, coords[1] + height)

# Public method: setBounds

    def setBounds(self, x, y=None, width=None, height=None):
        """
        Changes the bounds of this rectangle to the specified values.
        """
        if type(x) is GRectangle:
            width, height = x.getWidth(), x.getHeight()
            x, y = x.getX(), x.getY()
        self.setLocation(x, y)
        self.setSize(width, height)

# Override method: getBounds

    def getBounds(self):
        """
        Returns the bounds of this <code>GRect</code>.
        """
        return GRectangle(self.x, self.y, self.width, self.height)

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GRect"

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GRect</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        self.tkid = tkc.create_rectangle(x, y,
                                         x + self.width, y + self.height,
                                         width=self.lineWidth)
        self.updateColor()

# Override method: __str__

    def __str__(self):
        return ("GRect(" + str(self.x) + ", " + str(self.y) + ", " +
                str(self.width) + ", " + str(self.height) + ")")

# Class: GOval

class GOval(GFillableObject):
    """
    This graphical object subclass represents an oval inscribed in
    a rectangular box.
    """

# Constructor: GOval

    def __init__(self, a1, a2, a3=None, a4=None):
        """
        The <code>GOval</code> constructor takes either of the following
        forms:

        <pre>
           GOval(width, height)
           GOval(x, y, width, height)
        </pre>

        If the <code>x</code> and <code>y</code> parameters are missing,
        the origin is set to (0, 0).
        """
        GFillableObject.__init__(self)
        if a3 is None:
            x = 0
            y = 0
            width = a1
            height = a2
        else:
            x = a1
            y = a2
            width = a3
            height = a4
        self.width = width
        self.height = height
        self.setLocation(x, y)

# Public method: setSize

    def setSize(self, width, height=None):
        """
        Changes the size of this oval as specified.
        """
        if type(width) is GDimension:
            width, height = width.getWidth(), width.getHeight()
        self.width = width
        self.height = height
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        tkc.coords(self.tkid, coords[0], coords[1],
                   coords[0] + width, coords[1] + height)

# Public method: setBounds

    def setBounds(self, x, y=None, width=None, height=None):
        """
        Changes the bounds of this rectangle to the specified values.
        """
        if type(x) is GRectangle:
            width, height = x.getWidth(), x.getHeight()
            x, y = x.getX(), x.getY()
        self.setLocation(x, y)
        self.setSize(width, height)

# Override method: getBounds

    def getBounds(self):
        """
        Returns the bounds of this <code>GOval</code>.
        """
        return GRectangle(self.x, self.y, self.width, self.height)

# Override method: contains

    def contains(self, x, y):
        rx = self.width / 2
        ry = self.height / 2
        tx = x - (self.x + rx)
        ty = y - (self.y + ry)
        return (tx * tx) / (rx * rx) + (ty * ty) / (ry * ry) <= 1.0

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GOval"

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GOval</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.x, self.y))
        x = pt.getX()
        y = pt.getY()
        self.tkid = tkc.create_oval(x, y,
                                    x + self.width, y + self.height,
                                    width=self.lineWidth)

        self.updateColor()

# Override method: __str__

    def __str__(self):
        return ("GOval(" + str(self.x) + ", " + str(self.y) + ", " +
                str(self.width) + ", " + str(self.height) + ")")

# Class: GCompound

class GCompound(GObject):
    """
    This graphical object subclass consists of a collection of other
    graphical objects.  Once assembled, the internal objects can be
    manipulated as a unit.  The <code>GCompound</code> keeps track
    of its own position, and all items within it are drawn relative
    to that location.
    """

# Constructor: GCompound

    def __init__(self):
        """
        Creates a <code>GCompound</code> with no internal components.
        """
        GObject.__init__(self)
        self.contents = [ ]

# Public method: add

    def add(self, gobj, x=None, y=None):
        """
        Adds a new graphical object to the <code>GCompound</code>.  The
        first parameter is the object to be added.  The <code>x</code>
        and <code>y</code> parameters are optional.  If they are supplied,
        the location of the object is set to (<code>x</code>, <code>y</code>).
        """
        if x is not None:
            gobj.setLocation(x, y)
        self.contents.append(gobj)
        gobj.parent = self
        if self.gw is None:
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()
        else:
            gobj._install(self.gw, SimpleTransform())

# Public method: remove

    def remove(self, gobj):
        """
        Removes the specified object from the <code>GCompound</code>.
        """
        index = self.findGObject(gobj)
        if index != -1:
            self.removeAt(index)
        gw = self.getWindow()
        if gw is not None:
            gw._rebuild()

# Public method: removeAll

    def removeAll(self):
        """
        Removes all graphical objects from the <code>GCompound</code>.
        """
        while (len(self.contents) > 0):
            self.removeAt(0)
        gw = self.getWindow()
        if gw is not None:
            gw._rebuild()

# Public method: getElementAt

    def getElementAt(self, x, y):
        """
        Returns the topmost <code>GObject</code> containing the
        point (x, y), or <code>None</code> if no such object exists.
        Coordinates are interpreted relative to the reference point.
        """
        for gobj in reversed(self.contents):
            if gobj.contains(x, y):
                return gobj
        return None

# Public method: getElementCount

    def getElementCount(self):
        """
        Returns the number of graphical objects stored in the
        <code>GCompound</code>.
        """
        return len(self.contents)

# Public method: getElement

    def getElement(self, index):
        """
        Returns the graphical object at the specified index, numbering
        from back to front in the the <i>z</i> dimension.
        """
        return self.contents[index]

# Override method: getBounds

    def getBounds(self):
        """
        Returns a bounding rectangle for this compound.
        """
        x0 = self.getX()
        y0 = self.getY()
        if len(self.contents) == 0:
            return GRectangle(x0, y0, 0, 0)
        xMin = sys.float_info.max
        yMin = sys.float_info.max
        xMax = sys.float_info.min
        yMax = sys.float_info.min
        for gobj in self.contents:
            bounds = gobj.getBounds()
            xMin = min(xMin, x0 + bounds.getX())
            yMin = min(yMin, y0 + bounds.getY())
            xMax = max(xMax, x0 + bounds.getX())
            yMax = max(yMax, y0 + bounds.getY())
            xMin = min(xMin, x0 + bounds.getX() + bounds.getWidth())
            yMin = min(yMin, y0 + bounds.getY() + bounds.getHeight())
            xMax = max(xMax, x0 + bounds.getX() + bounds.getWidth())
            yMax = max(yMax, y0 + bounds.getY() + bounds.getHeight())
        return GRectangle(xMin, yMin, xMax - xMin, yMax - yMin)

# Public method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        refpt = self.getLocation()
        tx = x - refpt.getX()
        ty = y - refpt.getY()
        for gobj in self.contents:
            if gobj.contains(tx, ty):
                return True
        return False

# Override method: getType

    def getType(self):
        """
        Returns the type of this object
        """
        return "GCompound"

# Public method: __str__

    def __str__(self):
        return "GCompound(...)"

# Override method: _updateLocation

    def _updateLocation(self):
        """
        Updates the location for this <code>GCompound</code> by
        rebuilding the entire window if the component is installed.
        """
        gw = self.getWindow()
        if gw is not None:
            gw._rebuild()

# Override method: _install

    def _install(self, target, ctm):
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        ctm2 = SimpleTransform(pt.getX(), pt.getY())
        for gobj in self.contents:
            gobj._install(target, ctm2)

# Internal method: _sendForward

    def _sendForward(self, gobj):
        index = self.findGObject(gobj)
        if index == -1:
            return
        if index != len(self.contents) - 1:
            self.contents.pop(index)
            self.contents.insert(index + 1, gobj)
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()

# Internal method: _sendToFront

    def _sendToFront(self, gobj):
        index = self.findGObject(gobj)
        if index == -1:
            return
        if index != len(self.contents) - 1:
            self.contents.pop(index)
            self.contents.append(gobj)
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()

# Internal method: _sendBackward

    def _sendBackward(self, gobj):
        index = self.findGObject(gobj)
        if index == -1:
            return
        if index != 0:
            self.contents.pop(index)
            self.contents.insert(index - 1, gobj)
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()

# Internal method: _sendToBack

    def _sendToBack(self, gobj):
        index = self.findGObject(gobj)
        if index == -1:
            return
        if index != 0:
            self.contents.pop(index)
            self.contents.insert(0, gobj)
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()

# Internal method: findGObject

    def findGObject(self, gobj):
        n = len(self.contents)
        for i in range(n):
            if self.contents[i] == gobj:
                return i
        return -1

# Internal method: removeAt

    def removeAt(self, index):
        gobj = self.contents[index]
        self.contents.pop(index)
        gobj.parent = None

# Class: GArc

class GArc(GFillableObject):
    """
    This graphical object subclass represents an elliptical arc.  The
    arc is specified by the following parameters::

    <ul>
       <li>The coordinates of the bounding rectangle (x, y, width, height)</li>
       <li>The angle at which the arc starts (start)</li>
       <li>The number of degrees that the arc covers (sweep)</li>
    </ul>

    All angles in a <code>GArc</code> description are measured in
    degrees moving counterclockwise from the +<i>x</i> axis.  Negative
    values for either <code>start</code> or <code>sweep</code> indicate
    motion in a clockwise direction.
    """

# Constructor: GArc

    def __init__(self, a1, a2, a3=None, a4=None, a5=None, a6=None):
        """
        The <code>GArc</code> constructor takes either of the following
        forms:

        <pre>
           GArc(width, height, start, sweep)
           GArc(x, y, width, height, start, sweep)
        </pre>

        If the <code>x</code> and <code>y</code> parameters are missing,
        the origin is set to (0, 0).
        """
        GFillableObject.__init__(self)
        if a5 is None:
            x = 0
            y = 0
            width = a1
            height = a2
            start = a3
            sweep = a4
        else:
            x = a1
            y = a2
            width = a3
            height = a4
            start = a5
            sweep = a6
        self.frameWidth = width
        self.frameHeight = height
        self.start = start
        self.sweep = sweep
        self.setLocation(x, y)

# Public method: setStartAngle

    def setStartAngle(self, start):
        """
        Sets the starting angle for this <code>GArc</code> object.
        """
        self.start = start
        self.updateProperties(start=start)

# Public method: getStartAngle

    def getStartAngle(self):
        """
        Returns the starting angle for this GArc object.
        """
        return self.start

# Public method: setSweepAngle

    def setSweepAngle(self, sweep):
        """
        Sets the sweep angle for this GArc object.
        """
        self.sweep = sweep
        self.updateProperties(extent=sweep)

# Public method: getSweepAngle

    def getSweepAngle(self):
        """
        Returns the sweep angle for this GArc object.
        """
        return self.sweep

# Public method: getStartPoint

    def getStartPoint(self):
        """
        Returns the point at which the arc starts.
        """
        return self.getArcPoint(self.start)

# Public method: getEndPoint

    def getEndPoint(self):
        """
        Returns the point at which the arc ends.
        """
        return self.getArcPoint(self.start + self.sweep)

# Public method: setFrameRectangle

    def setFrameRectangle(self, x, y=None, width=None, height=None):
        """
        Changes the boundaries of the rectangle used to frame the arc.
        """
        if type(x) is GRectangle:
            width, height = x.getWidth(), x.getHeight()
            x, y = x.getX(), x.getY()
        self.setLocation(x, y)
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        tkc.coords(self.tkid, coords[0], coords[1],
                   coords[0] + width, coords[1] + height)

# Public method: getFrameRectangle

    def getFrameRectangle(self):
        """
        Returns the boundaries of the rectangle used to frame the arc.
        """
        return GRectangle(self.x, self.y, self.frameWidth, self.frameHeight)

# Override method: setFilled

    def setFilled(self, flag):
        """
        Sets the fill status for the arc, where <code>False</code> is
        outlined and <code>True</code> is filled.  If a <code>GArc</code>
        is unfilled, the figure consists only of the arc itself.  If a
        <code>GArc</code> is filled, the figure consists of the
        pie-shaped wedge formed by connecting the endpoints of the arc to
        the center.
        """
        GFillableObject.setFilled(self, flag)
        style = tkinter.ARC
        if flag:
            style = tkinter.PIESLICE
        self.updateProperties(style=style)

# Public method: getBounds

    def getBounds(self):
        """
        Gets the bounding rectangle for this object
        """
        rx = self.frameWidth / 2
        ry = self.frameHeight / 2
        cx = self.x + rx
        cy = self.y + ry
        startRadians = self.start * math.pi / 180
        sweepRadians = self.sweep * math.pi / 180
        p1x = cx + math.cos(startRadians) * rx
        p1y = cy - math.sin(startRadians) * ry
        p2x = cx + math.cos(startRadians + sweepRadians) * rx
        p2y = cy - math.sin(startRadians + sweepRadians) * ry
        xMin = min(p1x, p2x)
        xMax = max(p1x, p2x)
        yMin = min(p1y, p2y)
        yMax = max(p1y, p2y)
        if self.containsAngle(0):
            xMax = cx + rx
        if self.containsAngle(90):
            yMin = cy - ry
        if self.containsAngle(180):
            xMin = cx - rx
        if self.containsAngle(270):
            yMax = cy + ry
        if self.isFilled():
            xMin = min(xMin, cx)
            yMin = min(yMin, cy)
            xMax = max(xMax, cx)
            yMax = max(yMax, cy)
        return GRectangle(xMin, yMin, xMax - xMin, yMax - yMin)

# Public method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        rx = self.frameWidth / 2
        ry = self.frameHeight / 2
        if rx == 0 or ry == 0:
            return False
        dx = x - (self.x + rx)
        dy = y - (self.y + ry)
        r = (dx * dx) / (rx * rx) + (dy * dy) / (ry * ry)
        if self.fillFlag:
            if r > 1.0:
                return False
        else:
            t = __ARC_TOLERANCE__ / ((rx + ry) / 2)
            if abs(1.0 - r) > t:
                return False
        return self.containsAngle(math.atan2(-dy, dx) * 180 / math.pi)

# Override method: getType

    def getType(self):
        """
        Returns the type of this object
        """
        return "GArc"

# Public method: __str__

    def __str__(self):
        return ("GArc(" + str(self.x) + ", " + str(self.y) + ", " +
                str(self.frameWidth) + ", " + str(self.frameHeight) + ", " +
                str(self.start) + ", " + str(self.sweep) + ")")

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GArc</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        style = tkinter.ARC
        if self.isFilled():
            style = tkinter.PIESLICE
        self.tkid = tkc.create_arc(x, y,
                                   x + self.frameWidth, y + self.frameHeight,
                                   start=self.start, extent=self.sweep,
                                   width=self.lineWidth, style=style)
        self.updateColor()

# Private method: getArcPoint

    def getArcPoint(self, theta):
        rx = self.frameWidth / 2
        ry = self.frameHeight / 2
        cx = self.x + rx
        cy = self.y + ry
        radians = theta * math.pi / 180
        return GPoint(cx + rx * math.cos(radians), cy - ry * math.sin(radians))

# Private method: containsAngle

    def containsAngle(self, theta):
        start = min(self.start, self.start + self.sweep)
        sweep = abs(self.sweep)
        if sweep >= 360:
            return True
        if theta < 0:
            theta = 360 - math.fmod(-theta, 360)
        else:
            theta = math.fmod(theta, 360)
        if start < 0:
            start = 360 - math.fmod(-start, 360)
        else:
            start = math.fmod(start, 360)
        if start + sweep > 360:
            return (theta >= start or theta <= start + sweep - 360)
        else:
            return (theta >= start and theta <= start + sweep)

# Class: GLine

class GLine(GObject):
    """
    This graphical object subclass represents a line segment.
    """

# Constructor: GLine

    def __init__(self, x0, y0, x1, y1):
        """
        Initializes a line segment from its endpoints.  The point
        (<code>x0</code>, <code>y0</code>) defines the start of the
        line and the point (<code>x1</code>, <code>y1</code>) defines
        the end.
        """
        GObject.__init__(self)
        self.x = x0
        self.y = y0
        self.dx = x1 - x0
        self.dy = y1 - y0

# Public method: setStartPoint

    def setStartPoint(self, x, y):
        """
        Sets the initial point to (<code>x</code>, <code>y</code>),
        leaving the end point unchanged.  This method is therefore
        different from <code>setLocation</code>, which moves both
        components of the line segment.
        """
        self.dx += self.x - x
        self.dy += self.y - y
        self.x = x
        self.y = y
        self.updatePoints()

# Public method: getStartPoint

    def getStartPoint(self):
        """
        Returns the point at which the line starts.
        """
        return GPoint(self.x, self.y)

# Public method: setEndPoint

    def setEndPoint(self, x, y):
        """
        Sets the end point in the line to (x, y), leaving the start point
        unchanged.
        """
        self.dx = x - self.x
        self.dy = y - self.y
        self.updatePoints()

# Public method: getEndPoint

    def getEndPoint(self):
        """
        Returns the point at which the line ends.
        """
        return GPoint(self.x + self.dx, self.y + self.dy)

# Overload method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        x0 = self.getX()
        y0 = self.getY()
        x1 = x0 + self.dx
        y1 = y0 + self.dy
        tSquared = __LINE_TOLERANCE__ * __LINE_TOLERANCE__
        if dsq(x, y, x0, y0) < tSquared:
            return True
        if dsq(x, y, x1, y1) < tSquared:
            return True
        if x < min(x0, x1) - __LINE_TOLERANCE__:
            return False
        if x > max(x0, x1) + __LINE_TOLERANCE__:
            return False
        if y < min(y0, y1) - __LINE_TOLERANCE__:
            return False
        if y > max(y0, y1) + __LINE_TOLERANCE__:
            return False
        if (x0 - x1) == 0 and (y0 - y1) == 0:
            return False
        d = dsq(x0, y0, x1, y1)
        u = ((x - x0) * (x1 - x0) + (y - y0) * (y1 - y0)) / d
        return dsq(x, y, x0 + u * (x1 - x0), y0 + u * (y1 - y0)) < tSquared

# Override method: getType

    def getType(self):
        """
        Returns the type of this object
        """
        return "GLine"

# Public method: __str__

    def __str__(self):
        return ("GLine(" + str(self.x) + ", " + str(self.y) + ", " +
                str(self.x + self.dx) + ", " + str(self.y + self.dy) + ")")

# Override method: getBounds

    def getBounds(self):
        """
        Returns the bounds of this <code>GLine</code>.
        """
        x0 = min(self.x, self.x + self.dx)
        y0 = min(self.y, self.y + self.dy)
        x1 = max(self.x, self.x + self.dx)
        y1 = max(self.y, self.y + self.dy)
        return GRectangle(x0, y0, x1 - x0, y1 - y0)

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GLine</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        self.tkid = tkc.create_line(x, y, x + self.dx, y + self.dy,
                                    width=self.getLineWidth(),
                                    fill=self.color)

# Private method: updatePoints

    def updatePoints(self):
        """
        Updates the points in the <code>GLine</code>.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        tkc.coords(self.tkid, self.x, self.y,
                   self.x + self.dx, self.y + self.dy)

# Class: GImage

class GImage(GObject):
    """
    This graphical object subclass represents an image from a file.
    """

    def __init__(self, source, x=0, y=0):
        """
        Initializes a new image by loading the image from the specified
        source, which is either the name of a file in the current directory
        or a two-dimensional array of pixels.
        """
        GObject.__init__(self)
        self.source = source
        self.imageModel = _imageModel
        if _imageModel == "PIL":
            if type(source) is str:
                self.image = Image.open(source)
                self.image.load()
            else:
                width = len(source[0])
                height = len(source)
                ba = bytearray(4 * width * height)
                for i in range(height):
                    for j in range(width):
                        argb = source[i][j]
                        base = 4 * (i * width + j)
                        ba[base] = (argb >> 16) & 0xFF
                        ba[base + 1] = (argb >> 8) & 0xFF
                        ba[base + 2] = argb & 0xFF
                        ba[base + 3] = (argb >> 24) & 0xFF
                self.image = Image.frombytes("RGBA", (width, height),
                                             bytes(ba))
            self.photo = ImageTk.PhotoImage(self.image)
        else:
            if type(source) is str:
                self.photo = tkinter.PhotoImage(file=source)
            else:
                raise ImportError("getPixelArray requires the Pillow library")
        self.setLocation(x, y)
        self.sf = 1

# Public method: getBounds

    def getBounds(self):
        """
        Returns the bounding rectangle for this object
        """
        photo = self.photo
        return GRectangle(self.x, self.y, photo.width(), photo.height())

# Public method: getPixelArray

    def getPixelArray(self):
        """
        Returns a two-dimensional array of integers containing the pixel data.
        """
        if self.imageModel == "PIL":
            image = self.image
            width = image.width
            height = image.height
        else:
            width = self.photo.width()
            height = self.photo.height()
        pixels = height * [ [ 0 ] ]
        for y in range(height):
            pixels[y] = width * [ 0 ]
        if self.imageModel == "PIL":
            data = image.convert("RGBA").getdata()
            i = 0
            for i in range(height):
                for j in range(width):
                    rgba = data[i * width + j]
                    p = rgba[3] << 24 | rgba[0] << 16 | rgba[1] << 8 | rgba[2]
                    pixels[i][j] = p
        return pixels

# Override method: scale

    def scale(self, sf):
        """
        Scales the GImage by the specified scale factor.
        """
        if self.imageModel != "PIL":
            raise Exception("Image scaling is available only if PIL is loaded")
        self.sf *= sf
        gw = self.getWindow()
        if gw is not None:
            gw._rebuild()

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GImage"

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GImage</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        if self.sf != 1:
            w = round(self.image.width * self.sf)
            h = round(self.image.height * self.sf)
            img = self.image.resize((w, h), Image.ANTIALIAS)
            self.photo = ImageTk.PhotoImage(img)
        self.tkid = tkc.create_image(x, y,
                                     anchor=tkinter.NW,
                                     image=self.photo)

# Static method: getRed

    @staticmethod
    def getRed(pixel):
        """
        Returns the red component of the pixel.
        """
        return pixel >> 16 & 0xFF

# Static method: getGreen

    @staticmethod
    def getGreen(pixel):
        """
        Returns the green component of the pixel.
        """
        return pixel >> 8 & 0xFF

# Static method: getBlue

    @staticmethod
    def getBlue(pixel):
        """
        Returns the blue component of the pixel.
        """
        return pixel & 0xFF

# Static method: getAlpha

    @staticmethod
    def getAlpha(pixel):
        """
        Returns the alpha component of the pixel.
        """
        return pixel >> 24 & 0xFF

# Static method: createRGBPixel

    @staticmethod
    def createRGBPixel(a1=None, a2=None, a3=None, a4=None, **kw):
        """
        Creates an RGB pixel from the arguments.  The kw dictionary allows
        clients to name these parameters to override the conventional order.
        """
        if a4 is None:
            a = 0xFF
            r = a1
            g = a2
            b = a3
        else:
            a = a1
            r = a2
            g = a3
            b = a4
        if "alpha" in kw:
            a = kw["alpha"]
        if "red" in kw:
            r = kw["red"]
        if "green" in kw:
            g = kw["green"]
        if "blue" in kw:
            b = kw["blue"]
        return a << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)

# Public method: __str__

    def __str__(self):
        if type(self.source) is str:
            return "GImage(\"" + self.source + "\")"
        else:
            return "GImage(<data>)"

# Class: GLabel

class GLabel(GObject):
    """
    This graphical object subclass represents a text string.
    """

# Constants

    DEFAULT_FONT = "13pt 'Helvetica Neue','Helvetica','Arial','Sans-Serif'"

# Constructor: GLabel

    def __init__(self, text, x=0, y=0):
        """
        Initializes a <code>GLabel</code> object containing the specified
        string.  By default, the baseline of the first character appears
        at the origin.
        """
        GObject.__init__(self)
        self.text = text
        self.font = self.DEFAULT_FONT
        self.tkFont = decodeFont(self.font)
        self.setLocation(x, y)

# Public method: setFont

    def setFont(self, font):
        """
        Changes the font used to display the GLabel as specified by
        <code>font</code>, which has the form <code>family-style-size</code>,
        where both <code>style</code> and <code>size</code> are optional.
        """
        self.font = font
        self.tkFont = decodeFont(self.font)
        self.updateProperties(font=self.tkFont)
        self._updateLocation()

# Public method: getFont

    def getFont(self):
        """
        Returns the current font for the GLabel.
        """
        return self.font

# Public method: setLabel

    def setLabel(self, text):
        """
        Changes the string stored within the GLabel object, so that
        a new text string appears on the display.
        """
        self.text = text
        self.updateProperties(text=text)

# Public method: getLabel

    def getLabel(self):
        """
        Returns the string displayed by this object.
        """
        return self.text

# Public method: getAscent

    def getAscent(self):
        """
        Returns the maximum distance strings in this font extend above
        the baseline.
        """
        return self.tkFont.metrics("ascent")

# Public method: getDescent

    def getDescent(self):
        """
        Returns the maximum distance strings in this font descend below
        the baseline.
        """
        return self.tkFont.metrics("descent")

# Override method: getWidth

    def getWidth(self):
        """
        Returns the width for this <code>GLabel</code>.
        """
        return self.tkFont.measure(self.text)

# Override method: getHeight

    def getHeight(self):
        """
        Returns the height for this <code>GLabel</code>.
        """
        return self.tkFont.metrics("linespace")

# Override method: getBounds

    def getBounds(self):
        """
        Returns the bounding rectangle for this object.
        """
        return GRectangle(self.x, self.y - self.getAscent(),
                          self.getWidth(), self.getHeight())

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GLabel"

# Override method: _updateLocation

    def _updateLocation(self):
        """
        Updates the location for this <code>GLabel</code> from the stored
        x and y values.  This override is necessary to adjust for the
        baseline.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        offx = 0
        offy = self.getHeight() - self.getAscent()
        gobj = self.getParent()
        while gobj is not None:
            offx += gobj.x
            offy += gobj.y
            gobj = gobj.getParent()
        dx = (self.x + offx) - coords[0]
        dy = (self.y + offy) - coords[1]
        tkc.move(self.tkid, dx, dy)

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GLabel</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        baseline = y + self.getHeight() - self.getAscent()
        self.tkid = tkc.create_text(x,
                                    baseline,
                                    text=self.text,
                                    font=self.tkFont,
                                    fill=self.color,
                                    anchor="sw")

# Override method: __str__

    def __str__(self):
        return "GLabel(\"" + self.str + "\")"

# Class: GPolygon

class GPolygon(GFillableObject):
    """
    This graphical object subclass represents a polygon bounded by line
    segments.  The <code>GPolygon</code> constructor creates an empty
    polygon.  To complete the figure, you need to add vertices to the
    polygon using some combination of the methods <code>addVertex</code>,
    <code>addEdge</code>, and <code>addPolarEdge</code>.
    """

# Constructor: GPolygon

    def __init__(self):
        """
        Initializes a new empty polygon at the origin.
        """
        GFillableObject.__init__(self)
        self.cx = None
        self.cy = None
        self.vertices = [ ]

# Public method: addVertex

    def addVertex(self, x, y):
        """
        Adds a vertex at (<code>x</code>, <code>y</code>) relative to the
        polygon origin.
        """
        self.cx = x
        self.cy = y
        self.vertices.append(GPoint(x, y))

# Public method: addEdge

    def addEdge(self, dx, dy):
        """
        Adds an edge to the polygon whose components are given by the
        displacements <code>dx</code> and <code>dy</code> from the
        last vertex.
        """
        self.addVertex(self.cx + dx, self.cy + dy)

# Public method: addPolarEdge

    def addPolarEdge(self, r, theta):
        """
        Adds an edge to the polygon specified in polar coordinates.  The
        length of the edge is given by <code>r</code>, and the edge extends
        in direction <code>theta</code>, measured in degrees counterclockwise
        from the +<i>x</i> axis.
        """
        self.addEdge(r * math.cos(theta * math.pi / 180),
                     -r * math.sin(theta * math.pi / 180))

# Public method: getVertices

    def getVertices(self):
        """
        Returns a list of the points in the polygon.
        """
        return self.vertices

# Public method: getBounds

    def getBounds(self):
        """
        Returns the bounding rectangle for this object.
        """
        xMin = 0
        yMin = 0
        xMax = 0
        yMax = 0
        for i in range(len(self.vertices)):
            x = self.vertices[i].getX()
            y = self.vertices[i].getY()
            if i == 0 or x < xMin:
                xMin = x
            if i == 0 or y < yMin:
                yMin = y
            if i == 0 or x > xMax:
                xMax = x
            if i == 0 or y > yMax:
                yMax = y
        x0 = self.getX()
        y0 = self.getY()
        return GRectangle(x0 + xMin, y0 + yMin, xMax - xMin, yMax - yMin)

# Public method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        tx = x - self.getX()
        ty = y - self.getY()
        crossings = 0
        n = len(self.vertices)
        if n < 2:
            return False
        if self.vertices[0] == self.vertices[n - 1]:
            n = n - 1
        x0 = self.vertices[0].getX()
        y0 = self.vertices[0].getY()
        for i in range(1, n + 1):
            x1 = self.vertices[i % n].getX()
            y1 = self.vertices[i % n].getY()
            if (y0 > ty) != (y1 > ty):
                if tx - x0 < (x1 - x0) * (ty - y0) / (y1 - y0):
                    crossings = crossings + 1
            x0 = x1
            y0 = y1
        return (crossings % 2 == 1)

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GPolygon"

# Public method: __str__

    def __str__(self):
        return "GPolygon(" + str(len(self.vertices)) + " vertices)"

# Override method: _updateLocation

    def _updateLocation(self):
        """
        Updates the location for this object from the stored x and y
        values.  Some subclasses need to override this method.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        dx = self.x - coords[0]
        dy = self.y - coords[1]
        tkc.move(self.tkid, dx, dy)

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GPolygon</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        coords = [ ]
        for pt in self.vertices:
            coords.append(pt.getX() + x)
            coords.append(pt.getY() + y)
        self.tkid = tkc.create_polygon(*coords, width=self.lineWidth)
        self.updateColor()

# Class: GPoint

class GPoint:
    """
    This class contains real-valued x and y fields. It is used to represent
    a location on the graphics plane.
    """

# Constructor: GPoint

    def __init__(self, x=0, y=0):
        """Initializes a point with the specified coordinates."""
        self._x = x
        self._y = y

# Public method: getX

    def getX(self):
        """Returns the x component of the point."""
        return self._x

# Public method: getY

    def getY(self):
        """Returns the y component of the point."""
        return self._y

# Public method: __str__

    def __str__(self):
        """Returns the string representation of a point."""
        return "(" + str(self._x) + ", " + str(self._y) + ")"

# Public method: __eq__

    def __eq__(self, other):
        """Returns a Boolean indicating whether two points are equal."""
        if type(other) is GPoint:
            return self._x == other._x and self._y == other._y
        return False

# Class: GDimension

class GDimension:
    """
    This class contains real-valued witdth and height fields.  It is
    used to indicate the size of a graphical object.
    """

# Constructor: GDimension

    def __init__(self, width=0.0, height=0.0):
        """
        Initializes a <code>GDimension</code> object with the specified size.
        """
        self._width = width
        self._height = height

# Public method: getWidth

    def getWidth(self):
        """
        Returns the width component of the <code>GDimension</code>.
        """
        return self._width

# Public method: getHeight

    def getHeight(self):
        """
        Returns the height component of the <code>GDimension</code>.
        """
        return self._height

# Public method: __str__

    def __str__(self):
        return "(" + str(self._width) + ", " + str(self._height) + ")"

# Public method: __eq__

    def __eq__(self, other):
        if type(other) is GDimension:
            return (self._width == other._width and
                    self._height == other._height)
        return False

# Class: GRectangle

class GRectangle:
    """
    This type contains real-valued x, y, width, and height fields. It is
    used to represent the bounding box of a graphical object.
    """

# Constructor: GRectangle

    def __init__(self, x=0.0, y=0.0, width=0.0, height=0.0):
        """
        Initializes a <code>GRectangle</code> object with the specified
        fields.
        """
        self._x = x
        self._y = y
        self._width = width
        self._height = height

# Public method: getX

    def getX(self):
        """
        Returns the x component of the upper left corner.
        """
        return self._x

# Public method: getY

    def getY(self):
        """
        Returns the x component of the upper left corner.
        """
        return self._y

# Public method: getWidth

    def getWidth(self):
        """
        Returns the width component of the GRectangle.
        """
        return self._width

# Public method: getHeight

    def getHeight(self):
        """
        Returns the width component of the GRectangle.
        """
        return self._height

# Public method: isEmpty

    def isEmpty(self):
        """
        Returns <code>True</code> if the rectangle is empty.
        """
        return self._width <= 0 or self._height <= 0

# Public method: contains

    def contains(self, x, y):
        """
        Returns <code>True</code> if the specified point is inside the
        rectangle.
        """
        if type(x) is GPoint:
            x, y = x.getX(), x.getY()
        elif type(x) is dict:
            x, y = x.x, x.y
        return (x >= self._x and
                y >= self._y and
                x < self._x + self._width and
                y < self._y + self._height)

# Public method: __str__

    def __str__(self):
        return ("(" + str(self._x) + ", " + str(self._y) + ", " +
                str(self._width) + ", " + str(self._height) + ")")

# Public method: __eq__

    def __eq__(self, other):
        if type(other) is GRectangle:
            return (self._x == other._x and
                    self._y == other._y and
                    self._width == other._width and
                    self._height == other._height)
        return False

# Class: GButton

class GButton(GCompound):

# Constants

    BUTTON_FONT = "14px 'Lucida Grande','Helvetica Neue','Sans-Serif'"
    BUTTON_MARGIN = 10
    BUTTON_MIN_WIDTH = 125
    BUTTON_DEFAULT_HEIGHT = 20
    BUTTON_ASCENT_DELTA = -1

# Constructor: GButton

    def __init__(self, text, fn=None):
        GCompound.__init__(self)
        label = GLabel(text)
        label.setFont(self.BUTTON_FONT)
        width = max(self.BUTTON_MIN_WIDTH,
                    2 * self.BUTTON_MARGIN + label.getWidth())
        frame = GRect(width, self.BUTTON_DEFAULT_HEIGHT)
        frame.setFilled(True)
        frame.setFillColor("White")
        self.add(frame)
        self.add(label)
        self.text = text
        self.label = label
        self.frame = frame
        self.fn = fn
        self._recenter()

# Public method: setSize

    def setSize(self, width, height):
        """
        Sets the dimensions of the button.
        """
        self.frame.setSize(width, height)
        self._recenter()

# Public method: setFont

    def setFont(self, font):
        """
        Sets the font for the button.
        """
        self.label.setFont(font)
        self._recenter()

# Public method: getFont

    def getFont(self):
        """
        Returns the font for the button.
        """
        return self.label.getFont()

# Public method: setLabel

    def setLabel(self, label):
        """
        Sets the label for the button.
        """
        self.label.setLabel(label)
        self._recenter()

# Public method: getLabel

    def getLabel(self):
        """
        Returns the label for the button.
        """
        return self.label.getLabel()

    def __str__(self):
        return "<Button " + self.text + ">"

    def _install(self, target, ctm):
        GCompound._install(self, target, ctm)
        if isinstance(target, GWindow):
            target.addEventListener("click", self._clickAction)

    def _clickAction(self, e):
        if self.contains(e.getX(), e.getY()):
            self.fn()

    def _recenter(self):
        x = (self.frame.getWidth() - self.label.getWidth()) / 2
        y = (self.frame.getHeight() + self.label.getAscent()) / 2
        self.label.setLocation(x, y + self.BUTTON_ASCENT_DELTA)

# Class: GTimer

class GTimer:
    """
    This type implements a timer running in the window.  This class supports
    both one-shot and interval timers.
    """

    def __init__(self, gw, fn, delay):
        self.gw = gw
        self.fn = fn
        self.delay = delay
        self.repeats = False
        self.afterId = None
        gw.timers.append(self)

    def timerTicked(self):
        self.timerStopped = False
        self.fn()
        if self.repeats and not self.timerStopped:
            tkc = self.gw.canvas
            self.afterId = tkc.after(self.delay, self.timerTicked)

    def setRepeats(self, flag):
        self.repeats = flag

    def start(self):
        tkc = self.gw.canvas
        self.afterId = tkc.after(self.delay, self.timerTicked)

    def stop(self):
        if self.afterId is not None:
            tkc = self.gw.canvas
            tkc.after_cancel(self.afterId)
            self.timerStopped = True
            self.afterId = None
        

# Class: GEvent

class GEvent(object):
    """
    This type is the abstract superclass for all events in the graphics
    package.
    """

# Constructor: GEvent

    def __init__(self):
        """
        Creates a new <code>GEvent</code> object.  This method should
        not be called by clients.
        """

# Public abstract method: getSource
        """
        Returns the source of this event.  Subclasses must override this
        method with an appropriate definition.
        """
        raise Exception("getSource is not defined in the base class")

# Class: GMouseEvent

class GMouseEvent(GEvent):
    """
    This class maintains the data for a mouse event.
    """

# Constructor: GMouseEvent

    def __init__(self, tke):
        """
        Creates a new <code>GMouseEvent</code> from the corresponding
        tkinter event tke.
        """
        self.x = tke.x
        self.y = tke.y

# Public method: getX

    def getX(self):
        """
        Returns the x coordinate of the mouse event.
        """
        return self.x

# Public method: getY

    def getY(self):
        """
        Returns the y coordinate of the mouse event.
        """
        return self.y

# Override method: getSource

    def getSource():
        """
        Returns the source of the mouse event, which is always the
        root window.
        """
        return tkinter._root

# Class: GKeyEvent

class GKeyEvent(GEvent):
    """
    This class maintains the data for a key event.
    """

# Constructor: GKeyEvent

    def __init__(self, tke):
        """
        Creates a new <code>GKeyEvent</code> from the corresponding
        tkinter event tke.
        """
        keysym = tke.keysym.upper()
        if len(keysym) > 1:
            underscore = keysym.find("_")
            if underscore > 0:
                self.key = "<" + keysym[0:underscore] + ">"
            else:
                self.key = "<" + keysym + ">"
        else:
            self.key = tke.char

# Public method: getKey

    def getKey(self):
        """
        Returns the character that triggered the event.  This will be
        a single-character string for normal keys and the name of the
        key enclosed in angle brackets for special keys like <RETURN>.
        """
        return self.key

# Override method: getSource

    def getSource():
        """
        Returns the source of the key event, which is always the
        root window.
        """
        return tkinter._root

# Function: pause

def pause(milliseconds):
    """
    Pauses for the indicated number of milliseconds.  This function is
    useful for animation where the motion would otherwise be too fast.
    """
    time.sleep(milliseconds / 1000)

# Function: getScreenWidth

def getScreenWidth():
    """
    Returns the width of the entire display screen.
    """
    return tkinter._root.winfo_screenwidth()

# Function: getScreenHeight

def getScreenHeight():
    """
    Returns the height of the entire display screen.
    """
    return tkinter._root.winfo_screenheight()

# Function: convertColorToRGB

def convertColorToRGB(colorName):
    """
    Converts a color name into an integer that encodes the
    red, green, and blue components of the color.
    """
    if colorName == "":
        return -1
    if colorName[0] == "#":
        colorName = "0x" + colorName[1:]
        return int(colorName, 16)
    name = canonicalColorName(colorName)
    if name not in COLOR_TABLE:
        raise Exception("setColor: Illegal color - " + colorName)
    return COLOR_TABLE[name]

# Function: convertRGBToColor

def convertRGBToColor(rgb):
    """
    Converts an rgb value into a name in the form <code>"#rrggbb"</code>.
    Each of the <code>rr</code>, <code>gg</code>, and <code>bb</code>
    values are two-digit hexadecimal numbers indicating the intensity
    of that component.
    """
    hexString = hex(0xFF000000 | rgb)
    return "#" + hexString[4:].upper()

# Function: exitGraphics

def exitGraphics():
    """
    Closes all graphics windows and exits from the application without
    waiting for any additional user interaction.
    """
    sys.exit()

# Function: getProgramName

def getProgramName():
    """
    Returns the name of the program.
    """
    name = None
    stack = inspect.stack()
    i = len(stack) - 1
    while i >= 0 and name is None:
        code = stack[i].code_context[stack[i].index]
        rf = code.find("runfile(")
        if rf >= 0:
            start = rf + len("runfile('")
            finish = code.find("'", start)
            name = code[start:finish]
        else:
            i -= 1
    if name is None:
        i = len(stack) - 1
        while i >= 0 and name is None:
            if stack[i].filename:
                name = stack[i].filename
            else:
                i -= 1
    if name is None:
        return "Graphics Window"
    name = name[name.rfind("/") + 1:]
    dot = name.find(".")
    if dot != -1:
        name = name[:dot]
    return name

# Private function: canonicalColorName

def canonicalColorName(str):
    result = ""
    for char in str:
        if not char.isspace() and char != "_":
            result += char.lower()
    return result

# Private function: dsq

def dsq(x0, y0, x1, y1):
    """
    Returns the square of the distance between two points.
    """
    return (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)

# Function: decodeFont

def decodeFont(name):
    """
    Parses a font string into a tkinter <code>Font</code> object.
    This method accepts a font in either the <code>Font.decode</code>
    used by Java or in the form of a CSS-based style string.
    """
    font = parseJSFont(name)
    if font is None:
        font = parseJavaFont(name)
    return font

def parseJSFont(name):
    """
    Attempts to parse a font specification as a JavaScript font.
    If the parse succeeds, <code>parseJSFont</code> returns the font.
    If the parse fails, <code>parseJSFont</code> returns <code>None</code>.
    """
    name = name.lower().strip()
    family = None
    size = -1
    weight = "normal"
    slant = "roman"
    start = 0
    while (size == -1):
        sp = name.find(" ", start)
        if sp == -1:
            return None
        token = name[start:sp]
        start = sp + 1
        if token == "bold":
            weight = "bold"
        elif token == "italic":
            slant = "italic"
        elif token[0].isdigit():
            size = parseJSUnits(token)
            if size == -1:
                return None
        else:
            return None
    families = name[start:].split(",")
    if len(families) == 0:
        return None
    for family in families:
        if family.startswith("'") or family.startswith("\""):
            family = family[1:-1]
        # // Add code to test for existence of font family
        return tkFont.Font(family=family, size=-size,
                           weight=weight, slant=slant)
    return None

def parseJavaFont(name):
    """
    Attempts to parse a font specification as a Java font.
    If the parse succeeds, <code>parseJavaFont</code> returns the font.
    If the parse fails, <code>parseJavaFont</code> returns <code>None</code>.
    """
    components = name.lower().strip().split("-")
    family = components[0]
    weight = "normal"
    slant = "roman"
    if components[1][0].isdigit():
        size = components[1]
    else:
        size = components[2]
        if "bold" in components[1]:
            weight = "bold"
        if "italic" in components[1]:
            slant = "italic"
    return tkFont.Font(family=family, size=-size,
                       weight=weight, slant=slant)

def parseJSUnits(spec):
    ux = len(spec)
    while (ux > 0 and spec[ux - 1] >= "A"):
        ux = ux - 1
    if ux == 0 or ux == len(spec):
        return -1
    value = float(spec[:ux])
    units = spec[ux:]
    if units == "em":
        return round(16 * value)
    elif units == "pt":
        return round(value / 0.75)
    else:
        return round(value)

# Private class: SimpleTransform

class SimpleTransform:

    def __init__(self, tx=0.0, ty=0.0, rotation=0.0, sf=1.0):
        self.tx = tx
        self.ty = ty
        self.rotation = rotation
        self.sf = sf

    def getTX(self):
        return self.tx

    def getTY(self):
        return self.ty

    def getRotation(self):
        return self.rotation

    def getSF(self):
        return self.sf

    # Current stub implementation assumes no rotation and scaling

    def transform(self, pt):
        x0 = pt.getX()
        y0 = pt.getY()
        if self.rotation == 0:
            x1 = self.tx + self.sf * x0
            y1 = self.ty + self.sf * y0
        else:
            ct = math.cos(math.radians(self.rotation))
            st = math.sin(math.radians(self.rotation))
            x1 = self.tx + self.sf * (x0 * ct + y0 * st)
            y1 = self.ty + self.sf * (y0 * ct - x0 * st)
        return GPoint(x1, y1)

    def compose(self, transform):
        return SimpleTransform(self.tx + transform.getTX(),
                               self.ty + transform.getTY())

# Private class: EventManager

class EventManager:
    CLICK_MAX_DISTANCE = 2
    CLICK_MAX_DELAY = 0.5
    pressHandler = None
    releaseHandler = None
    motionHandler = None
    dragHandler = None
    keyHandler = None
    clickListeners = [ ]
    dblclickListeners = [ ]
    mousedownListeners = [ ]
    mouseupListeners = [ ]
    mousemoveListeners = [ ]
    dragListeners = [ ]
    keyListeners = [ ]
    downX = None
    downY = None
    downTime = None

    def __init__(self, gw):
        self.gw = gw
        self.downX = -1
        self.downY = -1

    def pressAction(self, tke):
        self.downX = tke.x
        self.downY = tke.y
        self.downTime = time.time()
        e = GMouseEvent(tke)
        for fn in self.mousedownListeners:
            fn(e)

    def releaseAction(self, tke):
        e = GMouseEvent(tke)
        for fn in self.mouseupListeners:
            fn(e)
        if abs(self.downX - e.x) <= self.CLICK_MAX_DISTANCE:
            if abs(self.downY - e.y) <= self.CLICK_MAX_DISTANCE:
                if time.time() - self.downTime < self.CLICK_MAX_DELAY:
                    for fn in self.clickListeners:
                        fn(e)
        # // Implement dblclick

    def motionAction(self, tke):
        e = GMouseEvent(tke)
        for fn in self.mousemoveListeners:
            fn(e)

    def dragAction(self, tke):
        e = GMouseEvent(tke)
        for fn in self.dragListeners:
            fn(e)

    def keyAction(self, tke):
        e = GKeyEvent(tke)
        for fn in self.keyListeners:
            fn(e)

    def addEventListener(self, type, fn):
        tkc = self.gw.canvas
        if type == "click":
            if self.pressHandler is None:
                self.pressHandler = self.pressAction
                tkc.bind("<ButtonPress-1>", self.pressHandler)
            if self.releaseHandler is None:
                self.releaseHandler = self.releaseAction
                tkc.bind("<ButtonRelease-1>", self.releaseHandler)
            if fn not in self.clickListeners:
                self.clickListeners.append(fn)
        elif type == "mousedown" or type == "press":
            if self.pressHandler is None:
                self.pressHandler = self.pressAction
                tkc.bind("<ButtonPress-1>", self.pressHandler)
            if fn not in self.mousedownListeners:
                self.mousedownListeners.append(fn)
        elif type == "mouseup" or type == "release":
            if self.releaseHandler is None:
                self.releaseHandler = self.releaseAction
                tkc.bind("<ButtonRelease-1>", self.releaseHandler)
            if fn not in self.mouseupListeners:
                self.mouseupListeners.append(fn)
        elif type == "dblclick":
            if self.pressHandler is None:
                self.pressHandler = self.pressAction
                tkc.bind("<ButtonPress-1>", self.pressHandler)
            if self.releaseHandler is None:
                self.releaseHandler = self.releaseAction
                tkc.bind("<ButtonRelease-1>", self.releaseHandler)
            if fn not in self.dblclickListeners:
                self.dblclickListeners.append(fn)
        elif type == "mousemove" or type == "move":
            if self.motionHandler is None:
                self.motionHandler = self.motionAction
                tkc.bind("<Motion>", self.motionHandler)
            if fn not in self.mousemoveListeners:
                self.mousemoveListeners.append(fn)
        elif type == "drag":
            if self.dragHandler is None:
                self.dragHandler = self.dragAction
                tkc.bind("<B1-Motion>", self.dragHandler)
            if fn not in self.dragListeners:
                self.dragListeners.append(fn)
        elif type == "key":
            if self.keyHandler is None:
                self.keyHandler = self.keyAction
                tkc.bind("<Key>", self.keyHandler)
                tkc.focus_set()
            if fn not in self.keyListeners:
                self.keyListeners.append(fn)
        else:
            raise Exception("Illegal event type: " + type)

# Constants

__LINE_TOLERANCE__ = 2
__ARC_TOLERANCE__ = 2

# Color table

COLOR_TABLE = {
    "aliceblue": 0xF0F8FF,
    "antiquewhite": 0xFAEBD7,
    "aqua": 0x00FFFF,
    "aquamarine": 0x7FFFD4,
    "azure": 0xF0FFFF,
    "beige": 0xF5F5DC,
    "bisque": 0xFFE4C4,
    "black": 0x000000,
    "blanchedalmond": 0xFFEBCD,
    "blue": 0x0000FF,
    "blueviolet": 0x8A2BE2,
    "brown": 0xA52A2A,
    "burlywood": 0xDEB887,
    "cadetblue": 0x5F9EA0,
    "chartreuse": 0x7FFF00,
    "chocolate": 0xD2691E,
    "coral": 0xFF7F50,
    "cornflowerblue": 0x6495ED,
    "cornsilk": 0xFFF8DC,
    "crimson": 0xDC143C,
    "cyan": 0x00FFFF,
    "darkblue": 0x00008B,
    "darkcyan": 0x008B8B,
    "darkgoldenrod": 0xB8860B,
    "darkgray": 0xA9A9A9,
    "darkgrey": 0xA9A9A9,
    "darkgreen": 0x006400,
    "darkkhaki": 0xBDB76B,
    "darkmagenta": 0x8B008B,
    "darkolivegreen": 0x556B2F,
    "darkorange": 0xFF8C00,
    "darkorchid": 0x9932CC,
    "darkred": 0x8B0000,
    "darksalmon": 0xE9967A,
    "darkseagreen": 0x8FBC8F,
    "darkslateblue": 0x483D8B,
    "darkslategray": 0x2F4F4F,
    "darkslategrey": 0x2F4F4F,
    "darkturquoise": 0x00CED1,
    "darkviolet": 0x9400D3,
    "deeppink": 0xFF1493,
    "deepskyblue": 0x00BFFF,
    "dimgray": 0x696969,
    "dimgrey": 0x696969,
    "dodgerblue": 0x1E90FF,
    "firebrick": 0xB22222,
    "floralwhite": 0xFFFAF0,
    "forestgreen": 0x228B22,
    "fuchsia": 0xFF00FF,
    "gainsboro": 0xDCDCDC,
    "ghostwhite": 0xF8F8FF,
    "gold": 0xFFD700,
    "goldenrod": 0xDAA520,
    "gray": 0x808080,
    "grey": 0x808080,
    "green": 0x008000,
    "greenyellow": 0xADFF2F,
    "honeydew": 0xF0FFF0,
    "hotpink": 0xFF69B4,
    "indianred": 0xCD5C5C,
    "indigo": 0x4B0082,
    "ivory": 0xFFFFF0,
    "khaki": 0xF0E68C,
    "lavender": 0xE6E6FA,
    "lavenderblush": 0xFFF0F5,
    "lawngreen": 0x7CFC00,
    "lemonchiffon": 0xFFFACD,
    "lightblue": 0xADD8E6,
    "lightcoral": 0xF08080,
    "lightcyan": 0xE0FFFF,
    "lightgoldenrodyellow": 0xFAFAD2,
    "lightgray": 0xD3D3D3,
    "lightgrey": 0xD3D3D3,
    "lightgreen": 0x90EE90,
    "lightpink": 0xFFB6C1,
    "lightsalmon": 0xFFA07A,
    "lightseagreen": 0x20B2AA,
    "lightskyblue": 0x87CEFA,
    "lightslategray": 0x778899,
    "lightslategrey": 0x778899,
    "lightsteelblue": 0xB0C4DE,
    "lightyellow": 0xFFFFE0,
    "lime": 0x00FF00,
    "limegreen": 0x32CD32,
    "linen": 0xFAF0E6,
    "magenta": 0xFF00FF,
    "maroon": 0x800000,
    "mediumaquamarine": 0x66CDAA,
    "mediumblue": 0x0000CD,
    "mediumorchid": 0xBA55D3,
    "mediumpurple": 0x9370DB,
    "mediumseagreen": 0x3CB371,
    "mediumslateblue": 0x7B68EE,
    "mediumspringgreen": 0x00FA9A,
    "mediumturquoise": 0x48D1CC,
    "mediumvioletred": 0xC71585,
    "midnightblue": 0x191970,
    "mintcream": 0xF5FFFA,
    "mistyrose": 0xFFE4E1,
    "moccasin": 0xFFE4B5,
    "navajowhite": 0xFFDEAD,
    "navy": 0x000080,
    "oldlace": 0xFDF5E6,
    "olive": 0x808000,
    "olivedrab": 0x6B8E23,
    "orange": 0xFFA500,
    "orangered": 0xFF4500,
    "orchid": 0xDA70D6,
    "palegoldenrod": 0xEEE8AA,
    "palegreen": 0x98FB98,
    "paleturquoise": 0xAFEEEE,
    "palevioletred": 0xDB7093,
    "papayawhip": 0xFFEFD5,
    "peachpuff": 0xFFDAB9,
    "peru": 0xCD853F,
    "pink": 0xFFC0CB,
    "plum": 0xDDA0DD,
    "powderblue": 0xB0E0E6,
    "purple": 0x800080,
    "rebeccapurple": 0x663399,
    "red": 0xFF0000,
    "rosybrown": 0xBC8F8F,
    "royalblue": 0x4169E1,
    "saddlebrown": 0x8B4513,
    "salmon": 0xFA8072,
    "sandybrown": 0xF4A460,
    "seagreen": 0x2E8B57,
    "seashell": 0xFFF5EE,
    "sienna": 0xA0522D,
    "silver": 0xC0C0C0,
    "skyblue": 0x87CEEB,
    "slateblue": 0x6A5ACD,
    "slategray": 0x708090,
    "slategrey": 0x708090,
    "snow": 0xFFFAFA,
    "springgreen": 0x00FF7F,
    "steelblue": 0x4682B4,
    "tan": 0xD2B48C,
    "teal": 0x008080,
    "thistle": 0xD8BFD8,
    "tomato": 0xFF6347,
    "turquoise": 0x40E0D0,
    "violet": 0xEE82EE,
    "wheat": 0xF5DEB3,
    "white": 0xFFFFFF,
    "whitesmoke": 0xF5F5F5,
    "yellow": 0xFFFF00,
    "yellowgreen": 0x9ACD32,
    "color.black": 0x000000,
    "color.darkgray": 0x595959,
    "color.gray": 0x999999,
    "color.lightgray": 0xBFBFBF,
    "color.white": 0xFFFFFF,
    "color.red": 0xFF0000,
    "color.yellow": 0xFFFF00,
    "color.green": 0x00FF00,
    "color.cyan": 0x00FFFF,
    "color.blue": 0x0000FF,
    "color.magenta": 0xFF00FF,
    "color.orange": 0xFFC800,
    "color.pink": 0xFFAFAF
}

# Check for successful compilation

if __name__ == "__main__":
    print("pgl.py compiled successfully")

Functions

def canonicalColorName(str)
Expand source code
def canonicalColorName(str):
    result = ""
    for char in str:
        if not char.isspace() and char != "_":
            result += char.lower()
    return result
def convertColorToRGB(colorName)

Converts a color name into an integer that encodes the red, green, and blue components of the color.

Expand source code
def convertColorToRGB(colorName):
    """
    Converts a color name into an integer that encodes the
    red, green, and blue components of the color.
    """
    if colorName == "":
        return -1
    if colorName[0] == "#":
        colorName = "0x" + colorName[1:]
        return int(colorName, 16)
    name = canonicalColorName(colorName)
    if name not in COLOR_TABLE:
        raise Exception("setColor: Illegal color - " + colorName)
    return COLOR_TABLE[name]
def convertRGBToColor(rgb)

Converts an rgb value into a name in the form "#rrggbb". Each of the rr, gg, and bb values are two-digit hexadecimal numbers indicating the intensity of that component.

Expand source code
def convertRGBToColor(rgb):
    """
    Converts an rgb value into a name in the form <code>"#rrggbb"</code>.
    Each of the <code>rr</code>, <code>gg</code>, and <code>bb</code>
    values are two-digit hexadecimal numbers indicating the intensity
    of that component.
    """
    hexString = hex(0xFF000000 | rgb)
    return "#" + hexString[4:].upper()
def decodeFont(name)

Parses a font string into a tkinter Font object. This method accepts a font in either the Font.decode used by Java or in the form of a CSS-based style string.

Expand source code
def decodeFont(name):
    """
    Parses a font string into a tkinter <code>Font</code> object.
    This method accepts a font in either the <code>Font.decode</code>
    used by Java or in the form of a CSS-based style string.
    """
    font = parseJSFont(name)
    if font is None:
        font = parseJavaFont(name)
    return font
def dsq(x0, y0, x1, y1)

Returns the square of the distance between two points.

Expand source code
def dsq(x0, y0, x1, y1):
    """
    Returns the square of the distance between two points.
    """
    return (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)
def exitGraphics()

Closes all graphics windows and exits from the application without waiting for any additional user interaction.

Expand source code
def exitGraphics():
    """
    Closes all graphics windows and exits from the application without
    waiting for any additional user interaction.
    """
    sys.exit()
def getProgramName()

Returns the name of the program.

Expand source code
def getProgramName():
    """
    Returns the name of the program.
    """
    name = None
    stack = inspect.stack()
    i = len(stack) - 1
    while i >= 0 and name is None:
        code = stack[i].code_context[stack[i].index]
        rf = code.find("runfile(")
        if rf >= 0:
            start = rf + len("runfile('")
            finish = code.find("'", start)
            name = code[start:finish]
        else:
            i -= 1
    if name is None:
        i = len(stack) - 1
        while i >= 0 and name is None:
            if stack[i].filename:
                name = stack[i].filename
            else:
                i -= 1
    if name is None:
        return "Graphics Window"
    name = name[name.rfind("/") + 1:]
    dot = name.find(".")
    if dot != -1:
        name = name[:dot]
    return name
def getScreenHeight()

Returns the height of the entire display screen.

Expand source code
def getScreenHeight():
    """
    Returns the height of the entire display screen.
    """
    return tkinter._root.winfo_screenheight()
def getScreenWidth()

Returns the width of the entire display screen.

Expand source code
def getScreenWidth():
    """
    Returns the width of the entire display screen.
    """
    return tkinter._root.winfo_screenwidth()
def parseJSFont(name)

Attempts to parse a font specification as a JavaScript font. If the parse succeeds, parseJSFont returns the font. If the parse fails, parseJSFont returns None.

Expand source code
def parseJSFont(name):
    """
    Attempts to parse a font specification as a JavaScript font.
    If the parse succeeds, <code>parseJSFont</code> returns the font.
    If the parse fails, <code>parseJSFont</code> returns <code>None</code>.
    """
    name = name.lower().strip()
    family = None
    size = -1
    weight = "normal"
    slant = "roman"
    start = 0
    while (size == -1):
        sp = name.find(" ", start)
        if sp == -1:
            return None
        token = name[start:sp]
        start = sp + 1
        if token == "bold":
            weight = "bold"
        elif token == "italic":
            slant = "italic"
        elif token[0].isdigit():
            size = parseJSUnits(token)
            if size == -1:
                return None
        else:
            return None
    families = name[start:].split(",")
    if len(families) == 0:
        return None
    for family in families:
        if family.startswith("'") or family.startswith("\""):
            family = family[1:-1]
        # // Add code to test for existence of font family
        return tkFont.Font(family=family, size=-size,
                           weight=weight, slant=slant)
    return None
def parseJSUnits(spec)
Expand source code
def parseJSUnits(spec):
    ux = len(spec)
    while (ux > 0 and spec[ux - 1] >= "A"):
        ux = ux - 1
    if ux == 0 or ux == len(spec):
        return -1
    value = float(spec[:ux])
    units = spec[ux:]
    if units == "em":
        return round(16 * value)
    elif units == "pt":
        return round(value / 0.75)
    else:
        return round(value)
def parseJavaFont(name)

Attempts to parse a font specification as a Java font. If the parse succeeds, parseJavaFont returns the font. If the parse fails, parseJavaFont returns None.

Expand source code
def parseJavaFont(name):
    """
    Attempts to parse a font specification as a Java font.
    If the parse succeeds, <code>parseJavaFont</code> returns the font.
    If the parse fails, <code>parseJavaFont</code> returns <code>None</code>.
    """
    components = name.lower().strip().split("-")
    family = components[0]
    weight = "normal"
    slant = "roman"
    if components[1][0].isdigit():
        size = components[1]
    else:
        size = components[2]
        if "bold" in components[1]:
            weight = "bold"
        if "italic" in components[1]:
            slant = "italic"
    return tkFont.Font(family=family, size=-size,
                       weight=weight, slant=slant)
def pause(milliseconds)

Pauses for the indicated number of milliseconds. This function is useful for animation where the motion would otherwise be too fast.

Expand source code
def pause(milliseconds):
    """
    Pauses for the indicated number of milliseconds.  This function is
    useful for animation where the motion would otherwise be too fast.
    """
    time.sleep(milliseconds / 1000)

Classes

class EventManager (gw)
Expand source code
class EventManager:
    CLICK_MAX_DISTANCE = 2
    CLICK_MAX_DELAY = 0.5
    pressHandler = None
    releaseHandler = None
    motionHandler = None
    dragHandler = None
    keyHandler = None
    clickListeners = [ ]
    dblclickListeners = [ ]
    mousedownListeners = [ ]
    mouseupListeners = [ ]
    mousemoveListeners = [ ]
    dragListeners = [ ]
    keyListeners = [ ]
    downX = None
    downY = None
    downTime = None

    def __init__(self, gw):
        self.gw = gw
        self.downX = -1
        self.downY = -1

    def pressAction(self, tke):
        self.downX = tke.x
        self.downY = tke.y
        self.downTime = time.time()
        e = GMouseEvent(tke)
        for fn in self.mousedownListeners:
            fn(e)

    def releaseAction(self, tke):
        e = GMouseEvent(tke)
        for fn in self.mouseupListeners:
            fn(e)
        if abs(self.downX - e.x) <= self.CLICK_MAX_DISTANCE:
            if abs(self.downY - e.y) <= self.CLICK_MAX_DISTANCE:
                if time.time() - self.downTime < self.CLICK_MAX_DELAY:
                    for fn in self.clickListeners:
                        fn(e)
        # // Implement dblclick

    def motionAction(self, tke):
        e = GMouseEvent(tke)
        for fn in self.mousemoveListeners:
            fn(e)

    def dragAction(self, tke):
        e = GMouseEvent(tke)
        for fn in self.dragListeners:
            fn(e)

    def keyAction(self, tke):
        e = GKeyEvent(tke)
        for fn in self.keyListeners:
            fn(e)

    def addEventListener(self, type, fn):
        tkc = self.gw.canvas
        if type == "click":
            if self.pressHandler is None:
                self.pressHandler = self.pressAction
                tkc.bind("<ButtonPress-1>", self.pressHandler)
            if self.releaseHandler is None:
                self.releaseHandler = self.releaseAction
                tkc.bind("<ButtonRelease-1>", self.releaseHandler)
            if fn not in self.clickListeners:
                self.clickListeners.append(fn)
        elif type == "mousedown" or type == "press":
            if self.pressHandler is None:
                self.pressHandler = self.pressAction
                tkc.bind("<ButtonPress-1>", self.pressHandler)
            if fn not in self.mousedownListeners:
                self.mousedownListeners.append(fn)
        elif type == "mouseup" or type == "release":
            if self.releaseHandler is None:
                self.releaseHandler = self.releaseAction
                tkc.bind("<ButtonRelease-1>", self.releaseHandler)
            if fn not in self.mouseupListeners:
                self.mouseupListeners.append(fn)
        elif type == "dblclick":
            if self.pressHandler is None:
                self.pressHandler = self.pressAction
                tkc.bind("<ButtonPress-1>", self.pressHandler)
            if self.releaseHandler is None:
                self.releaseHandler = self.releaseAction
                tkc.bind("<ButtonRelease-1>", self.releaseHandler)
            if fn not in self.dblclickListeners:
                self.dblclickListeners.append(fn)
        elif type == "mousemove" or type == "move":
            if self.motionHandler is None:
                self.motionHandler = self.motionAction
                tkc.bind("<Motion>", self.motionHandler)
            if fn not in self.mousemoveListeners:
                self.mousemoveListeners.append(fn)
        elif type == "drag":
            if self.dragHandler is None:
                self.dragHandler = self.dragAction
                tkc.bind("<B1-Motion>", self.dragHandler)
            if fn not in self.dragListeners:
                self.dragListeners.append(fn)
        elif type == "key":
            if self.keyHandler is None:
                self.keyHandler = self.keyAction
                tkc.bind("<Key>", self.keyHandler)
                tkc.focus_set()
            if fn not in self.keyListeners:
                self.keyListeners.append(fn)
        else:
            raise Exception("Illegal event type: " + type)

Class variables

var CLICK_MAX_DELAY

Convert a string or number to a floating point number, if possible.

var CLICK_MAX_DISTANCE

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

>>> int('0b100', base=0)
4
var clickListeners

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

var dblclickListeners

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

var downTime
var downX
var downY
var dragHandler
var dragListeners

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

var keyHandler
var keyListeners

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

var motionHandler
var mousedownListeners

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

var mousemoveListeners

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

var mouseupListeners

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

var pressHandler
var releaseHandler

Methods

def addEventListener(self, type, fn)
Expand source code
def addEventListener(self, type, fn):
    tkc = self.gw.canvas
    if type == "click":
        if self.pressHandler is None:
            self.pressHandler = self.pressAction
            tkc.bind("<ButtonPress-1>", self.pressHandler)
        if self.releaseHandler is None:
            self.releaseHandler = self.releaseAction
            tkc.bind("<ButtonRelease-1>", self.releaseHandler)
        if fn not in self.clickListeners:
            self.clickListeners.append(fn)
    elif type == "mousedown" or type == "press":
        if self.pressHandler is None:
            self.pressHandler = self.pressAction
            tkc.bind("<ButtonPress-1>", self.pressHandler)
        if fn not in self.mousedownListeners:
            self.mousedownListeners.append(fn)
    elif type == "mouseup" or type == "release":
        if self.releaseHandler is None:
            self.releaseHandler = self.releaseAction
            tkc.bind("<ButtonRelease-1>", self.releaseHandler)
        if fn not in self.mouseupListeners:
            self.mouseupListeners.append(fn)
    elif type == "dblclick":
        if self.pressHandler is None:
            self.pressHandler = self.pressAction
            tkc.bind("<ButtonPress-1>", self.pressHandler)
        if self.releaseHandler is None:
            self.releaseHandler = self.releaseAction
            tkc.bind("<ButtonRelease-1>", self.releaseHandler)
        if fn not in self.dblclickListeners:
            self.dblclickListeners.append(fn)
    elif type == "mousemove" or type == "move":
        if self.motionHandler is None:
            self.motionHandler = self.motionAction
            tkc.bind("<Motion>", self.motionHandler)
        if fn not in self.mousemoveListeners:
            self.mousemoveListeners.append(fn)
    elif type == "drag":
        if self.dragHandler is None:
            self.dragHandler = self.dragAction
            tkc.bind("<B1-Motion>", self.dragHandler)
        if fn not in self.dragListeners:
            self.dragListeners.append(fn)
    elif type == "key":
        if self.keyHandler is None:
            self.keyHandler = self.keyAction
            tkc.bind("<Key>", self.keyHandler)
            tkc.focus_set()
        if fn not in self.keyListeners:
            self.keyListeners.append(fn)
    else:
        raise Exception("Illegal event type: " + type)
def dragAction(self, tke)
Expand source code
def dragAction(self, tke):
    e = GMouseEvent(tke)
    for fn in self.dragListeners:
        fn(e)
def keyAction(self, tke)
Expand source code
def keyAction(self, tke):
    e = GKeyEvent(tke)
    for fn in self.keyListeners:
        fn(e)
def motionAction(self, tke)
Expand source code
def motionAction(self, tke):
    e = GMouseEvent(tke)
    for fn in self.mousemoveListeners:
        fn(e)
def pressAction(self, tke)
Expand source code
def pressAction(self, tke):
    self.downX = tke.x
    self.downY = tke.y
    self.downTime = time.time()
    e = GMouseEvent(tke)
    for fn in self.mousedownListeners:
        fn(e)
def releaseAction(self, tke)
Expand source code
def releaseAction(self, tke):
    e = GMouseEvent(tke)
    for fn in self.mouseupListeners:
        fn(e)
    if abs(self.downX - e.x) <= self.CLICK_MAX_DISTANCE:
        if abs(self.downY - e.y) <= self.CLICK_MAX_DISTANCE:
            if time.time() - self.downTime < self.CLICK_MAX_DELAY:
                for fn in self.clickListeners:
                    fn(e)
class GArc (a1, a2, a3=None, a4=None, a5=None, a6=None)

This graphical object subclass represents an elliptical arc. The arc is specified by the following parameters::

  • The coordinates of the bounding rectangle (x, y, width, height)
  • The angle at which the arc starts (start)
  • The number of degrees that the arc covers (sweep)

All angles in a GArc description are measured in degrees moving counterclockwise from the +x axis. Negative values for either start or sweep indicate motion in a clockwise direction.

The GArc constructor takes either of the following forms:

   GArc(width, height, start, sweep)
   GArc(x, y, width, height, start, sweep)

If the x and y parameters are missing, the origin is set to (0, 0).

Expand source code
class GArc(GFillableObject):
    """
    This graphical object subclass represents an elliptical arc.  The
    arc is specified by the following parameters::

    <ul>
       <li>The coordinates of the bounding rectangle (x, y, width, height)</li>
       <li>The angle at which the arc starts (start)</li>
       <li>The number of degrees that the arc covers (sweep)</li>
    </ul>

    All angles in a <code>GArc</code> description are measured in
    degrees moving counterclockwise from the +<i>x</i> axis.  Negative
    values for either <code>start</code> or <code>sweep</code> indicate
    motion in a clockwise direction.
    """

# Constructor: GArc

    def __init__(self, a1, a2, a3=None, a4=None, a5=None, a6=None):
        """
        The <code>GArc</code> constructor takes either of the following
        forms:

        <pre>
           GArc(width, height, start, sweep)
           GArc(x, y, width, height, start, sweep)
        </pre>

        If the <code>x</code> and <code>y</code> parameters are missing,
        the origin is set to (0, 0).
        """
        GFillableObject.__init__(self)
        if a5 is None:
            x = 0
            y = 0
            width = a1
            height = a2
            start = a3
            sweep = a4
        else:
            x = a1
            y = a2
            width = a3
            height = a4
            start = a5
            sweep = a6
        self.frameWidth = width
        self.frameHeight = height
        self.start = start
        self.sweep = sweep
        self.setLocation(x, y)

# Public method: setStartAngle

    def setStartAngle(self, start):
        """
        Sets the starting angle for this <code>GArc</code> object.
        """
        self.start = start
        self.updateProperties(start=start)

# Public method: getStartAngle

    def getStartAngle(self):
        """
        Returns the starting angle for this GArc object.
        """
        return self.start

# Public method: setSweepAngle

    def setSweepAngle(self, sweep):
        """
        Sets the sweep angle for this GArc object.
        """
        self.sweep = sweep
        self.updateProperties(extent=sweep)

# Public method: getSweepAngle

    def getSweepAngle(self):
        """
        Returns the sweep angle for this GArc object.
        """
        return self.sweep

# Public method: getStartPoint

    def getStartPoint(self):
        """
        Returns the point at which the arc starts.
        """
        return self.getArcPoint(self.start)

# Public method: getEndPoint

    def getEndPoint(self):
        """
        Returns the point at which the arc ends.
        """
        return self.getArcPoint(self.start + self.sweep)

# Public method: setFrameRectangle

    def setFrameRectangle(self, x, y=None, width=None, height=None):
        """
        Changes the boundaries of the rectangle used to frame the arc.
        """
        if type(x) is GRectangle:
            width, height = x.getWidth(), x.getHeight()
            x, y = x.getX(), x.getY()
        self.setLocation(x, y)
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        tkc.coords(self.tkid, coords[0], coords[1],
                   coords[0] + width, coords[1] + height)

# Public method: getFrameRectangle

    def getFrameRectangle(self):
        """
        Returns the boundaries of the rectangle used to frame the arc.
        """
        return GRectangle(self.x, self.y, self.frameWidth, self.frameHeight)

# Override method: setFilled

    def setFilled(self, flag):
        """
        Sets the fill status for the arc, where <code>False</code> is
        outlined and <code>True</code> is filled.  If a <code>GArc</code>
        is unfilled, the figure consists only of the arc itself.  If a
        <code>GArc</code> is filled, the figure consists of the
        pie-shaped wedge formed by connecting the endpoints of the arc to
        the center.
        """
        GFillableObject.setFilled(self, flag)
        style = tkinter.ARC
        if flag:
            style = tkinter.PIESLICE
        self.updateProperties(style=style)

# Public method: getBounds

    def getBounds(self):
        """
        Gets the bounding rectangle for this object
        """
        rx = self.frameWidth / 2
        ry = self.frameHeight / 2
        cx = self.x + rx
        cy = self.y + ry
        startRadians = self.start * math.pi / 180
        sweepRadians = self.sweep * math.pi / 180
        p1x = cx + math.cos(startRadians) * rx
        p1y = cy - math.sin(startRadians) * ry
        p2x = cx + math.cos(startRadians + sweepRadians) * rx
        p2y = cy - math.sin(startRadians + sweepRadians) * ry
        xMin = min(p1x, p2x)
        xMax = max(p1x, p2x)
        yMin = min(p1y, p2y)
        yMax = max(p1y, p2y)
        if self.containsAngle(0):
            xMax = cx + rx
        if self.containsAngle(90):
            yMin = cy - ry
        if self.containsAngle(180):
            xMin = cx - rx
        if self.containsAngle(270):
            yMax = cy + ry
        if self.isFilled():
            xMin = min(xMin, cx)
            yMin = min(yMin, cy)
            xMax = max(xMax, cx)
            yMax = max(yMax, cy)
        return GRectangle(xMin, yMin, xMax - xMin, yMax - yMin)

# Public method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        rx = self.frameWidth / 2
        ry = self.frameHeight / 2
        if rx == 0 or ry == 0:
            return False
        dx = x - (self.x + rx)
        dy = y - (self.y + ry)
        r = (dx * dx) / (rx * rx) + (dy * dy) / (ry * ry)
        if self.fillFlag:
            if r > 1.0:
                return False
        else:
            t = __ARC_TOLERANCE__ / ((rx + ry) / 2)
            if abs(1.0 - r) > t:
                return False
        return self.containsAngle(math.atan2(-dy, dx) * 180 / math.pi)

# Override method: getType

    def getType(self):
        """
        Returns the type of this object
        """
        return "GArc"

# Public method: __str__

    def __str__(self):
        return ("GArc(" + str(self.x) + ", " + str(self.y) + ", " +
                str(self.frameWidth) + ", " + str(self.frameHeight) + ", " +
                str(self.start) + ", " + str(self.sweep) + ")")

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GArc</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        style = tkinter.ARC
        if self.isFilled():
            style = tkinter.PIESLICE
        self.tkid = tkc.create_arc(x, y,
                                   x + self.frameWidth, y + self.frameHeight,
                                   start=self.start, extent=self.sweep,
                                   width=self.lineWidth, style=style)
        self.updateColor()

# Private method: getArcPoint

    def getArcPoint(self, theta):
        rx = self.frameWidth / 2
        ry = self.frameHeight / 2
        cx = self.x + rx
        cy = self.y + ry
        radians = theta * math.pi / 180
        return GPoint(cx + rx * math.cos(radians), cy - ry * math.sin(radians))

# Private method: containsAngle

    def containsAngle(self, theta):
        start = min(self.start, self.start + self.sweep)
        sweep = abs(self.sweep)
        if sweep >= 360:
            return True
        if theta < 0:
            theta = 360 - math.fmod(-theta, 360)
        else:
            theta = math.fmod(theta, 360)
        if start < 0:
            start = 360 - math.fmod(-start, 360)
        else:
            start = math.fmod(start, 360)
        if start + sweep > 360:
            return (theta >= start or theta <= start + sweep - 360)
        else:
            return (theta >= start and theta <= start + sweep)

Ancestors

Methods

def containsAngle(self, theta)
Expand source code
def containsAngle(self, theta):
    start = min(self.start, self.start + self.sweep)
    sweep = abs(self.sweep)
    if sweep >= 360:
        return True
    if theta < 0:
        theta = 360 - math.fmod(-theta, 360)
    else:
        theta = math.fmod(theta, 360)
    if start < 0:
        start = 360 - math.fmod(-start, 360)
    else:
        start = math.fmod(start, 360)
    if start + sweep > 360:
        return (theta >= start or theta <= start + sweep - 360)
    else:
        return (theta >= start and theta <= start + sweep)
def getArcPoint(self, theta)
Expand source code
def getArcPoint(self, theta):
    rx = self.frameWidth / 2
    ry = self.frameHeight / 2
    cx = self.x + rx
    cy = self.y + ry
    radians = theta * math.pi / 180
    return GPoint(cx + rx * math.cos(radians), cy - ry * math.sin(radians))
def getBounds(self)

Gets the bounding rectangle for this object

Expand source code
def getBounds(self):
    """
    Gets the bounding rectangle for this object
    """
    rx = self.frameWidth / 2
    ry = self.frameHeight / 2
    cx = self.x + rx
    cy = self.y + ry
    startRadians = self.start * math.pi / 180
    sweepRadians = self.sweep * math.pi / 180
    p1x = cx + math.cos(startRadians) * rx
    p1y = cy - math.sin(startRadians) * ry
    p2x = cx + math.cos(startRadians + sweepRadians) * rx
    p2y = cy - math.sin(startRadians + sweepRadians) * ry
    xMin = min(p1x, p2x)
    xMax = max(p1x, p2x)
    yMin = min(p1y, p2y)
    yMax = max(p1y, p2y)
    if self.containsAngle(0):
        xMax = cx + rx
    if self.containsAngle(90):
        yMin = cy - ry
    if self.containsAngle(180):
        xMin = cx - rx
    if self.containsAngle(270):
        yMax = cy + ry
    if self.isFilled():
        xMin = min(xMin, cx)
        yMin = min(yMin, cy)
        xMax = max(xMax, cx)
        yMax = max(yMax, cy)
    return GRectangle(xMin, yMin, xMax - xMin, yMax - yMin)
def getEndPoint(self)

Returns the point at which the arc ends.

Expand source code
def getEndPoint(self):
    """
    Returns the point at which the arc ends.
    """
    return self.getArcPoint(self.start + self.sweep)
def getFrameRectangle(self)

Returns the boundaries of the rectangle used to frame the arc.

Expand source code
def getFrameRectangle(self):
    """
    Returns the boundaries of the rectangle used to frame the arc.
    """
    return GRectangle(self.x, self.y, self.frameWidth, self.frameHeight)
def getStartAngle(self)

Returns the starting angle for this GArc object.

Expand source code
def getStartAngle(self):
    """
    Returns the starting angle for this GArc object.
    """
    return self.start
def getStartPoint(self)

Returns the point at which the arc starts.

Expand source code
def getStartPoint(self):
    """
    Returns the point at which the arc starts.
    """
    return self.getArcPoint(self.start)
def getSweepAngle(self)

Returns the sweep angle for this GArc object.

Expand source code
def getSweepAngle(self):
    """
    Returns the sweep angle for this GArc object.
    """
    return self.sweep
def getType(self)

Returns the type of this object

Expand source code
def getType(self):
    """
    Returns the type of this object
    """
    return "GArc"
def setFilled(self, flag)

Sets the fill status for the arc, where False is outlined and True is filled. If a GArc is unfilled, the figure consists only of the arc itself. If a GArc is filled, the figure consists of the pie-shaped wedge formed by connecting the endpoints of the arc to the center.

Expand source code
def setFilled(self, flag):
    """
    Sets the fill status for the arc, where <code>False</code> is
    outlined and <code>True</code> is filled.  If a <code>GArc</code>
    is unfilled, the figure consists only of the arc itself.  If a
    <code>GArc</code> is filled, the figure consists of the
    pie-shaped wedge formed by connecting the endpoints of the arc to
    the center.
    """
    GFillableObject.setFilled(self, flag)
    style = tkinter.ARC
    if flag:
        style = tkinter.PIESLICE
    self.updateProperties(style=style)
def setFrameRectangle(self, x, y=None, width=None, height=None)

Changes the boundaries of the rectangle used to frame the arc.

Expand source code
def setFrameRectangle(self, x, y=None, width=None, height=None):
    """
    Changes the boundaries of the rectangle used to frame the arc.
    """
    if type(x) is GRectangle:
        width, height = x.getWidth(), x.getHeight()
        x, y = x.getX(), x.getY()
    self.setLocation(x, y)
    gw = self.getWindow()
    if gw is None:
        return
    tkc = gw.canvas
    coords = tkc.coords(self.tkid)
    tkc.coords(self.tkid, coords[0], coords[1],
               coords[0] + width, coords[1] + height)
def setStartAngle(self, start)

Sets the starting angle for this GArc object.

Expand source code
def setStartAngle(self, start):
    """
    Sets the starting angle for this <code>GArc</code> object.
    """
    self.start = start
    self.updateProperties(start=start)
def setSweepAngle(self, sweep)

Sets the sweep angle for this GArc object.

Expand source code
def setSweepAngle(self, sweep):
    """
    Sets the sweep angle for this GArc object.
    """
    self.sweep = sweep
    self.updateProperties(extent=sweep)

Inherited members

class GButton (text, fn=None)

This graphical object subclass consists of a collection of other graphical objects. Once assembled, the internal objects can be manipulated as a unit. The GCompound keeps track of its own position, and all items within it are drawn relative to that location.

Creates a GCompound with no internal components.

Expand source code
class GButton(GCompound):

# Constants

    BUTTON_FONT = "14px 'Lucida Grande','Helvetica Neue','Sans-Serif'"
    BUTTON_MARGIN = 10
    BUTTON_MIN_WIDTH = 125
    BUTTON_DEFAULT_HEIGHT = 20
    BUTTON_ASCENT_DELTA = -1

# Constructor: GButton

    def __init__(self, text, fn=None):
        GCompound.__init__(self)
        label = GLabel(text)
        label.setFont(self.BUTTON_FONT)
        width = max(self.BUTTON_MIN_WIDTH,
                    2 * self.BUTTON_MARGIN + label.getWidth())
        frame = GRect(width, self.BUTTON_DEFAULT_HEIGHT)
        frame.setFilled(True)
        frame.setFillColor("White")
        self.add(frame)
        self.add(label)
        self.text = text
        self.label = label
        self.frame = frame
        self.fn = fn
        self._recenter()

# Public method: setSize

    def setSize(self, width, height):
        """
        Sets the dimensions of the button.
        """
        self.frame.setSize(width, height)
        self._recenter()

# Public method: setFont

    def setFont(self, font):
        """
        Sets the font for the button.
        """
        self.label.setFont(font)
        self._recenter()

# Public method: getFont

    def getFont(self):
        """
        Returns the font for the button.
        """
        return self.label.getFont()

# Public method: setLabel

    def setLabel(self, label):
        """
        Sets the label for the button.
        """
        self.label.setLabel(label)
        self._recenter()

# Public method: getLabel

    def getLabel(self):
        """
        Returns the label for the button.
        """
        return self.label.getLabel()

    def __str__(self):
        return "<Button " + self.text + ">"

    def _install(self, target, ctm):
        GCompound._install(self, target, ctm)
        if isinstance(target, GWindow):
            target.addEventListener("click", self._clickAction)

    def _clickAction(self, e):
        if self.contains(e.getX(), e.getY()):
            self.fn()

    def _recenter(self):
        x = (self.frame.getWidth() - self.label.getWidth()) / 2
        y = (self.frame.getHeight() + self.label.getAscent()) / 2
        self.label.setLocation(x, y + self.BUTTON_ASCENT_DELTA)

Ancestors

Class variables

var BUTTON_ASCENT_DELTA

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

>>> int('0b100', base=0)
4
var BUTTON_DEFAULT_HEIGHT

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

>>> int('0b100', base=0)
4
var BUTTON_FONT

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

var BUTTON_MARGIN

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

>>> int('0b100', base=0)
4
var BUTTON_MIN_WIDTH

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

>>> int('0b100', base=0)
4

Methods

def getFont(self)

Returns the font for the button.

Expand source code
def getFont(self):
    """
    Returns the font for the button.
    """
    return self.label.getFont()
def getLabel(self)

Returns the label for the button.

Expand source code
def getLabel(self):
    """
    Returns the label for the button.
    """
    return self.label.getLabel()
def setFont(self, font)

Sets the font for the button.

Expand source code
def setFont(self, font):
    """
    Sets the font for the button.
    """
    self.label.setFont(font)
    self._recenter()
def setLabel(self, label)

Sets the label for the button.

Expand source code
def setLabel(self, label):
    """
    Sets the label for the button.
    """
    self.label.setLabel(label)
    self._recenter()
def setSize(self, width, height)

Sets the dimensions of the button.

Expand source code
def setSize(self, width, height):
    """
    Sets the dimensions of the button.
    """
    self.frame.setSize(width, height)
    self._recenter()

Inherited members

class GCompound

This graphical object subclass consists of a collection of other graphical objects. Once assembled, the internal objects can be manipulated as a unit. The GCompound keeps track of its own position, and all items within it are drawn relative to that location.

Creates a GCompound with no internal components.

Expand source code
class GCompound(GObject):
    """
    This graphical object subclass consists of a collection of other
    graphical objects.  Once assembled, the internal objects can be
    manipulated as a unit.  The <code>GCompound</code> keeps track
    of its own position, and all items within it are drawn relative
    to that location.
    """

# Constructor: GCompound

    def __init__(self):
        """
        Creates a <code>GCompound</code> with no internal components.
        """
        GObject.__init__(self)
        self.contents = [ ]

# Public method: add

    def add(self, gobj, x=None, y=None):
        """
        Adds a new graphical object to the <code>GCompound</code>.  The
        first parameter is the object to be added.  The <code>x</code>
        and <code>y</code> parameters are optional.  If they are supplied,
        the location of the object is set to (<code>x</code>, <code>y</code>).
        """
        if x is not None:
            gobj.setLocation(x, y)
        self.contents.append(gobj)
        gobj.parent = self
        if self.gw is None:
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()
        else:
            gobj._install(self.gw, SimpleTransform())

# Public method: remove

    def remove(self, gobj):
        """
        Removes the specified object from the <code>GCompound</code>.
        """
        index = self.findGObject(gobj)
        if index != -1:
            self.removeAt(index)
        gw = self.getWindow()
        if gw is not None:
            gw._rebuild()

# Public method: removeAll

    def removeAll(self):
        """
        Removes all graphical objects from the <code>GCompound</code>.
        """
        while (len(self.contents) > 0):
            self.removeAt(0)
        gw = self.getWindow()
        if gw is not None:
            gw._rebuild()

# Public method: getElementAt

    def getElementAt(self, x, y):
        """
        Returns the topmost <code>GObject</code> containing the
        point (x, y), or <code>None</code> if no such object exists.
        Coordinates are interpreted relative to the reference point.
        """
        for gobj in reversed(self.contents):
            if gobj.contains(x, y):
                return gobj
        return None

# Public method: getElementCount

    def getElementCount(self):
        """
        Returns the number of graphical objects stored in the
        <code>GCompound</code>.
        """
        return len(self.contents)

# Public method: getElement

    def getElement(self, index):
        """
        Returns the graphical object at the specified index, numbering
        from back to front in the the <i>z</i> dimension.
        """
        return self.contents[index]

# Override method: getBounds

    def getBounds(self):
        """
        Returns a bounding rectangle for this compound.
        """
        x0 = self.getX()
        y0 = self.getY()
        if len(self.contents) == 0:
            return GRectangle(x0, y0, 0, 0)
        xMin = sys.float_info.max
        yMin = sys.float_info.max
        xMax = sys.float_info.min
        yMax = sys.float_info.min
        for gobj in self.contents:
            bounds = gobj.getBounds()
            xMin = min(xMin, x0 + bounds.getX())
            yMin = min(yMin, y0 + bounds.getY())
            xMax = max(xMax, x0 + bounds.getX())
            yMax = max(yMax, y0 + bounds.getY())
            xMin = min(xMin, x0 + bounds.getX() + bounds.getWidth())
            yMin = min(yMin, y0 + bounds.getY() + bounds.getHeight())
            xMax = max(xMax, x0 + bounds.getX() + bounds.getWidth())
            yMax = max(yMax, y0 + bounds.getY() + bounds.getHeight())
        return GRectangle(xMin, yMin, xMax - xMin, yMax - yMin)

# Public method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        refpt = self.getLocation()
        tx = x - refpt.getX()
        ty = y - refpt.getY()
        for gobj in self.contents:
            if gobj.contains(tx, ty):
                return True
        return False

# Override method: getType

    def getType(self):
        """
        Returns the type of this object
        """
        return "GCompound"

# Public method: __str__

    def __str__(self):
        return "GCompound(...)"

# Override method: _updateLocation

    def _updateLocation(self):
        """
        Updates the location for this <code>GCompound</code> by
        rebuilding the entire window if the component is installed.
        """
        gw = self.getWindow()
        if gw is not None:
            gw._rebuild()

# Override method: _install

    def _install(self, target, ctm):
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        ctm2 = SimpleTransform(pt.getX(), pt.getY())
        for gobj in self.contents:
            gobj._install(target, ctm2)

# Internal method: _sendForward

    def _sendForward(self, gobj):
        index = self.findGObject(gobj)
        if index == -1:
            return
        if index != len(self.contents) - 1:
            self.contents.pop(index)
            self.contents.insert(index + 1, gobj)
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()

# Internal method: _sendToFront

    def _sendToFront(self, gobj):
        index = self.findGObject(gobj)
        if index == -1:
            return
        if index != len(self.contents) - 1:
            self.contents.pop(index)
            self.contents.append(gobj)
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()

# Internal method: _sendBackward

    def _sendBackward(self, gobj):
        index = self.findGObject(gobj)
        if index == -1:
            return
        if index != 0:
            self.contents.pop(index)
            self.contents.insert(index - 1, gobj)
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()

# Internal method: _sendToBack

    def _sendToBack(self, gobj):
        index = self.findGObject(gobj)
        if index == -1:
            return
        if index != 0:
            self.contents.pop(index)
            self.contents.insert(0, gobj)
            gw = self.getWindow()
            if gw is not None:
                gw._rebuild()

# Internal method: findGObject

    def findGObject(self, gobj):
        n = len(self.contents)
        for i in range(n):
            if self.contents[i] == gobj:
                return i
        return -1

# Internal method: removeAt

    def removeAt(self, index):
        gobj = self.contents[index]
        self.contents.pop(index)
        gobj.parent = None

Ancestors

Subclasses

Methods

def add(self, gobj, x=None, y=None)

Adds a new graphical object to the GCompound. The first parameter is the object to be added. The x and y parameters are optional. If they are supplied, the location of the object is set to (x, y).

Expand source code
def add(self, gobj, x=None, y=None):
    """
    Adds a new graphical object to the <code>GCompound</code>.  The
    first parameter is the object to be added.  The <code>x</code>
    and <code>y</code> parameters are optional.  If they are supplied,
    the location of the object is set to (<code>x</code>, <code>y</code>).
    """
    if x is not None:
        gobj.setLocation(x, y)
    self.contents.append(gobj)
    gobj.parent = self
    if self.gw is None:
        gw = self.getWindow()
        if gw is not None:
            gw._rebuild()
    else:
        gobj._install(self.gw, SimpleTransform())
def findGObject(self, gobj)
Expand source code
def findGObject(self, gobj):
    n = len(self.contents)
    for i in range(n):
        if self.contents[i] == gobj:
            return i
    return -1
def getBounds(self)

Returns a bounding rectangle for this compound.

Expand source code
def getBounds(self):
    """
    Returns a bounding rectangle for this compound.
    """
    x0 = self.getX()
    y0 = self.getY()
    if len(self.contents) == 0:
        return GRectangle(x0, y0, 0, 0)
    xMin = sys.float_info.max
    yMin = sys.float_info.max
    xMax = sys.float_info.min
    yMax = sys.float_info.min
    for gobj in self.contents:
        bounds = gobj.getBounds()
        xMin = min(xMin, x0 + bounds.getX())
        yMin = min(yMin, y0 + bounds.getY())
        xMax = max(xMax, x0 + bounds.getX())
        yMax = max(yMax, y0 + bounds.getY())
        xMin = min(xMin, x0 + bounds.getX() + bounds.getWidth())
        yMin = min(yMin, y0 + bounds.getY() + bounds.getHeight())
        xMax = max(xMax, x0 + bounds.getX() + bounds.getWidth())
        yMax = max(yMax, y0 + bounds.getY() + bounds.getHeight())
    return GRectangle(xMin, yMin, xMax - xMin, yMax - yMin)
def getElement(self, index)

Returns the graphical object at the specified index, numbering from back to front in the the z dimension.

Expand source code
def getElement(self, index):
    """
    Returns the graphical object at the specified index, numbering
    from back to front in the the <i>z</i> dimension.
    """
    return self.contents[index]
def getElementAt(self, x, y)

Returns the topmost GObject containing the point (x, y), or None if no such object exists. Coordinates are interpreted relative to the reference point.

Expand source code
def getElementAt(self, x, y):
    """
    Returns the topmost <code>GObject</code> containing the
    point (x, y), or <code>None</code> if no such object exists.
    Coordinates are interpreted relative to the reference point.
    """
    for gobj in reversed(self.contents):
        if gobj.contains(x, y):
            return gobj
    return None
def getElementCount(self)

Returns the number of graphical objects stored in the GCompound.

Expand source code
def getElementCount(self):
    """
    Returns the number of graphical objects stored in the
    <code>GCompound</code>.
    """
    return len(self.contents)
def getType(self)

Returns the type of this object

Expand source code
def getType(self):
    """
    Returns the type of this object
    """
    return "GCompound"
def remove(self, gobj)

Removes the specified object from the GCompound.

Expand source code
def remove(self, gobj):
    """
    Removes the specified object from the <code>GCompound</code>.
    """
    index = self.findGObject(gobj)
    if index != -1:
        self.removeAt(index)
    gw = self.getWindow()
    if gw is not None:
        gw._rebuild()
def removeAll(self)

Removes all graphical objects from the GCompound.

Expand source code
def removeAll(self):
    """
    Removes all graphical objects from the <code>GCompound</code>.
    """
    while (len(self.contents) > 0):
        self.removeAt(0)
    gw = self.getWindow()
    if gw is not None:
        gw._rebuild()
def removeAt(self, index)
Expand source code
def removeAt(self, index):
    gobj = self.contents[index]
    self.contents.pop(index)
    gobj.parent = None

Inherited members

class GDimension (width=0.0, height=0.0)

This class contains real-valued witdth and height fields. It is used to indicate the size of a graphical object.

Initializes a GDimension object with the specified size.

Expand source code
class GDimension:
    """
    This class contains real-valued witdth and height fields.  It is
    used to indicate the size of a graphical object.
    """

# Constructor: GDimension

    def __init__(self, width=0.0, height=0.0):
        """
        Initializes a <code>GDimension</code> object with the specified size.
        """
        self._width = width
        self._height = height

# Public method: getWidth

    def getWidth(self):
        """
        Returns the width component of the <code>GDimension</code>.
        """
        return self._width

# Public method: getHeight

    def getHeight(self):
        """
        Returns the height component of the <code>GDimension</code>.
        """
        return self._height

# Public method: __str__

    def __str__(self):
        return "(" + str(self._width) + ", " + str(self._height) + ")"

# Public method: __eq__

    def __eq__(self, other):
        if type(other) is GDimension:
            return (self._width == other._width and
                    self._height == other._height)
        return False

Methods

def getHeight(self)

Returns the height component of the GDimension.

Expand source code
def getHeight(self):
    """
    Returns the height component of the <code>GDimension</code>.
    """
    return self._height
def getWidth(self)

Returns the width component of the GDimension.

Expand source code
def getWidth(self):
    """
    Returns the width component of the <code>GDimension</code>.
    """
    return self._width
class GEvent

This type is the abstract superclass for all events in the graphics package.

Creates a new GEvent object. This method should not be called by clients.

Expand source code
class GEvent(object):
    """
    This type is the abstract superclass for all events in the graphics
    package.
    """

# Constructor: GEvent

    def __init__(self):
        """
        Creates a new <code>GEvent</code> object.  This method should
        not be called by clients.
        """

# Public abstract method: getSource
        """
        Returns the source of this event.  Subclasses must override this
        method with an appropriate definition.
        """
        raise Exception("getSource is not defined in the base class")

Subclasses

class GFillableObject

This abstract class is the superclass of all objects that are fillable.

Initializes a GFillableObject. Because this is an abstract class, clients should not call this constructor explicitly.

Expand source code
class GFillableObject(GObject):
    """
    This abstract class is the superclass of all objects that are fillable.
    """

# Constructor: GFillableObject

    def __init__(self):
        """
        Initializes a <code>GFillableObject</code>.  Because this is an
        abstract class, clients should not call this constructor explicitly.
        """
        GObject.__init__(self)
        self.fillFlag = False
        self.fillColor = ""

# Public method: setFilled

    def setFilled(self, flag):
        """
        Sets the fill status for the object, where <code>False</code>
        is outlined and <code>True</code> is filled.
        """
        self.fillFlag = flag
        self.updateColor()

# Public method: isFilled

    def isFilled(self):
        """
        Returns <code>True</code> if the object is filled.
        """
        return self.fillFlag

# Public method: setFillColor

    def setFillColor(self, color):
        """
        Sets the color used to display the filled region of the object.
        """
        rgb = convertColorToRGB(color)
        self.fillColor = convertRGBToColor(rgb)
        self.updateColor()

# Public method: getFillColor

    def getFillColor(self):
        """
        Returns the color used to display the filled region of this
        object.  If no fill color has been set, <code>getFillColor</code>
        returns the empty string.
        """
        return self.fillColor

# Override method: updateColor

    def updateColor(self):
        """
        Updates the color properties for a <code>GFillableObject</code>.
        """
        outline = self.color
        if self.fillFlag:
            fill = self.fillColor
            if fill is None or fill == "":
                fill = outline
        else:
            fill = ""
        self.updateProperties(outline=outline, fill=fill)

Ancestors

Subclasses

Methods

def getFillColor(self)

Returns the color used to display the filled region of this object. If no fill color has been set, getFillColor returns the empty string.

Expand source code
def getFillColor(self):
    """
    Returns the color used to display the filled region of this
    object.  If no fill color has been set, <code>getFillColor</code>
    returns the empty string.
    """
    return self.fillColor
def isFilled(self)

Returns True if the object is filled.

Expand source code
def isFilled(self):
    """
    Returns <code>True</code> if the object is filled.
    """
    return self.fillFlag
def setFillColor(self, color)

Sets the color used to display the filled region of the object.

Expand source code
def setFillColor(self, color):
    """
    Sets the color used to display the filled region of the object.
    """
    rgb = convertColorToRGB(color)
    self.fillColor = convertRGBToColor(rgb)
    self.updateColor()
def setFilled(self, flag)

Sets the fill status for the object, where False is outlined and True is filled.

Expand source code
def setFilled(self, flag):
    """
    Sets the fill status for the object, where <code>False</code>
    is outlined and <code>True</code> is filled.
    """
    self.fillFlag = flag
    self.updateColor()
def updateColor(self)

Updates the color properties for a GFillableObject.

Expand source code
def updateColor(self):
    """
    Updates the color properties for a <code>GFillableObject</code>.
    """
    outline = self.color
    if self.fillFlag:
        fill = self.fillColor
        if fill is None or fill == "":
            fill = outline
    else:
        fill = ""
    self.updateProperties(outline=outline, fill=fill)

Inherited members

class GImage (source, x=0, y=0)

This graphical object subclass represents an image from a file.

Initializes a new image by loading the image from the specified source, which is either the name of a file in the current directory or a two-dimensional array of pixels.

Expand source code
class GImage(GObject):
    """
    This graphical object subclass represents an image from a file.
    """

    def __init__(self, source, x=0, y=0):
        """
        Initializes a new image by loading the image from the specified
        source, which is either the name of a file in the current directory
        or a two-dimensional array of pixels.
        """
        GObject.__init__(self)
        self.source = source
        self.imageModel = _imageModel
        if _imageModel == "PIL":
            if type(source) is str:
                self.image = Image.open(source)
                self.image.load()
            else:
                width = len(source[0])
                height = len(source)
                ba = bytearray(4 * width * height)
                for i in range(height):
                    for j in range(width):
                        argb = source[i][j]
                        base = 4 * (i * width + j)
                        ba[base] = (argb >> 16) & 0xFF
                        ba[base + 1] = (argb >> 8) & 0xFF
                        ba[base + 2] = argb & 0xFF
                        ba[base + 3] = (argb >> 24) & 0xFF
                self.image = Image.frombytes("RGBA", (width, height),
                                             bytes(ba))
            self.photo = ImageTk.PhotoImage(self.image)
        else:
            if type(source) is str:
                self.photo = tkinter.PhotoImage(file=source)
            else:
                raise ImportError("getPixelArray requires the Pillow library")
        self.setLocation(x, y)
        self.sf = 1

# Public method: getBounds

    def getBounds(self):
        """
        Returns the bounding rectangle for this object
        """
        photo = self.photo
        return GRectangle(self.x, self.y, photo.width(), photo.height())

# Public method: getPixelArray

    def getPixelArray(self):
        """
        Returns a two-dimensional array of integers containing the pixel data.
        """
        if self.imageModel == "PIL":
            image = self.image
            width = image.width
            height = image.height
        else:
            width = self.photo.width()
            height = self.photo.height()
        pixels = height * [ [ 0 ] ]
        for y in range(height):
            pixels[y] = width * [ 0 ]
        if self.imageModel == "PIL":
            data = image.convert("RGBA").getdata()
            i = 0
            for i in range(height):
                for j in range(width):
                    rgba = data[i * width + j]
                    p = rgba[3] << 24 | rgba[0] << 16 | rgba[1] << 8 | rgba[2]
                    pixels[i][j] = p
        return pixels

# Override method: scale

    def scale(self, sf):
        """
        Scales the GImage by the specified scale factor.
        """
        if self.imageModel != "PIL":
            raise Exception("Image scaling is available only if PIL is loaded")
        self.sf *= sf
        gw = self.getWindow()
        if gw is not None:
            gw._rebuild()

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GImage"

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GImage</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        if self.sf != 1:
            w = round(self.image.width * self.sf)
            h = round(self.image.height * self.sf)
            img = self.image.resize((w, h), Image.ANTIALIAS)
            self.photo = ImageTk.PhotoImage(img)
        self.tkid = tkc.create_image(x, y,
                                     anchor=tkinter.NW,
                                     image=self.photo)

# Static method: getRed

    @staticmethod
    def getRed(pixel):
        """
        Returns the red component of the pixel.
        """
        return pixel >> 16 & 0xFF

# Static method: getGreen

    @staticmethod
    def getGreen(pixel):
        """
        Returns the green component of the pixel.
        """
        return pixel >> 8 & 0xFF

# Static method: getBlue

    @staticmethod
    def getBlue(pixel):
        """
        Returns the blue component of the pixel.
        """
        return pixel & 0xFF

# Static method: getAlpha

    @staticmethod
    def getAlpha(pixel):
        """
        Returns the alpha component of the pixel.
        """
        return pixel >> 24 & 0xFF

# Static method: createRGBPixel

    @staticmethod
    def createRGBPixel(a1=None, a2=None, a3=None, a4=None, **kw):
        """
        Creates an RGB pixel from the arguments.  The kw dictionary allows
        clients to name these parameters to override the conventional order.
        """
        if a4 is None:
            a = 0xFF
            r = a1
            g = a2
            b = a3
        else:
            a = a1
            r = a2
            g = a3
            b = a4
        if "alpha" in kw:
            a = kw["alpha"]
        if "red" in kw:
            r = kw["red"]
        if "green" in kw:
            g = kw["green"]
        if "blue" in kw:
            b = kw["blue"]
        return a << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)

# Public method: __str__

    def __str__(self):
        if type(self.source) is str:
            return "GImage(\"" + self.source + "\")"
        else:
            return "GImage(<data>)"

Ancestors

Static methods

def createRGBPixel(a1=None, a2=None, a3=None, a4=None, **kw)

Creates an RGB pixel from the arguments. The kw dictionary allows clients to name these parameters to override the conventional order.

Expand source code
@staticmethod
def createRGBPixel(a1=None, a2=None, a3=None, a4=None, **kw):
    """
    Creates an RGB pixel from the arguments.  The kw dictionary allows
    clients to name these parameters to override the conventional order.
    """
    if a4 is None:
        a = 0xFF
        r = a1
        g = a2
        b = a3
    else:
        a = a1
        r = a2
        g = a3
        b = a4
    if "alpha" in kw:
        a = kw["alpha"]
    if "red" in kw:
        r = kw["red"]
    if "green" in kw:
        g = kw["green"]
    if "blue" in kw:
        b = kw["blue"]
    return a << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)
def getAlpha(pixel)

Returns the alpha component of the pixel.

Expand source code
@staticmethod
def getAlpha(pixel):
    """
    Returns the alpha component of the pixel.
    """
    return pixel >> 24 & 0xFF
def getBlue(pixel)

Returns the blue component of the pixel.

Expand source code
@staticmethod
def getBlue(pixel):
    """
    Returns the blue component of the pixel.
    """
    return pixel & 0xFF
def getGreen(pixel)

Returns the green component of the pixel.

Expand source code
@staticmethod
def getGreen(pixel):
    """
    Returns the green component of the pixel.
    """
    return pixel >> 8 & 0xFF
def getRed(pixel)

Returns the red component of the pixel.

Expand source code
@staticmethod
def getRed(pixel):
    """
    Returns the red component of the pixel.
    """
    return pixel >> 16 & 0xFF

Methods

def getBounds(self)

Returns the bounding rectangle for this object

Expand source code
def getBounds(self):
    """
    Returns the bounding rectangle for this object
    """
    photo = self.photo
    return GRectangle(self.x, self.y, photo.width(), photo.height())
def getPixelArray(self)

Returns a two-dimensional array of integers containing the pixel data.

Expand source code
def getPixelArray(self):
    """
    Returns a two-dimensional array of integers containing the pixel data.
    """
    if self.imageModel == "PIL":
        image = self.image
        width = image.width
        height = image.height
    else:
        width = self.photo.width()
        height = self.photo.height()
    pixels = height * [ [ 0 ] ]
    for y in range(height):
        pixels[y] = width * [ 0 ]
    if self.imageModel == "PIL":
        data = image.convert("RGBA").getdata()
        i = 0
        for i in range(height):
            for j in range(width):
                rgba = data[i * width + j]
                p = rgba[3] << 24 | rgba[0] << 16 | rgba[1] << 8 | rgba[2]
                pixels[i][j] = p
    return pixels
def getType(self)

Returns the type of this object.

Expand source code
def getType(self):
    """
    Returns the type of this object.
    """
    return "GImage"
def scale(self, sf)

Scales the GImage by the specified scale factor.

Expand source code
def scale(self, sf):
    """
    Scales the GImage by the specified scale factor.
    """
    if self.imageModel != "PIL":
        raise Exception("Image scaling is available only if PIL is loaded")
    self.sf *= sf
    gw = self.getWindow()
    if gw is not None:
        gw._rebuild()

Inherited members

class GKeyEvent (tke)

This class maintains the data for a key event.

Creates a new GKeyEvent from the corresponding tkinter event tke.

Expand source code
class GKeyEvent(GEvent):
    """
    This class maintains the data for a key event.
    """

# Constructor: GKeyEvent

    def __init__(self, tke):
        """
        Creates a new <code>GKeyEvent</code> from the corresponding
        tkinter event tke.
        """
        keysym = tke.keysym.upper()
        if len(keysym) > 1:
            underscore = keysym.find("_")
            if underscore > 0:
                self.key = "<" + keysym[0:underscore] + ">"
            else:
                self.key = "<" + keysym + ">"
        else:
            self.key = tke.char

# Public method: getKey

    def getKey(self):
        """
        Returns the character that triggered the event.  This will be
        a single-character string for normal keys and the name of the
        key enclosed in angle brackets for special keys like <RETURN>.
        """
        return self.key

# Override method: getSource

    def getSource():
        """
        Returns the source of the key event, which is always the
        root window.
        """
        return tkinter._root

Ancestors

Methods

def getKey(self)

Returns the character that triggered the event. This will be a single-character string for normal keys and the name of the key enclosed in angle brackets for special keys like .

Expand source code
def getKey(self):
    """
    Returns the character that triggered the event.  This will be
    a single-character string for normal keys and the name of the
    key enclosed in angle brackets for special keys like <RETURN>.
    """
    return self.key
def getSource()

Returns the source of the key event, which is always the root window.

Expand source code
def getSource():
    """
    Returns the source of the key event, which is always the
    root window.
    """
    return tkinter._root
class GLabel (text, x=0, y=0)

This graphical object subclass represents a text string.

Initializes a GLabel object containing the specified string. By default, the baseline of the first character appears at the origin.

Expand source code
class GLabel(GObject):
    """
    This graphical object subclass represents a text string.
    """

# Constants

    DEFAULT_FONT = "13pt 'Helvetica Neue','Helvetica','Arial','Sans-Serif'"

# Constructor: GLabel

    def __init__(self, text, x=0, y=0):
        """
        Initializes a <code>GLabel</code> object containing the specified
        string.  By default, the baseline of the first character appears
        at the origin.
        """
        GObject.__init__(self)
        self.text = text
        self.font = self.DEFAULT_FONT
        self.tkFont = decodeFont(self.font)
        self.setLocation(x, y)

# Public method: setFont

    def setFont(self, font):
        """
        Changes the font used to display the GLabel as specified by
        <code>font</code>, which has the form <code>family-style-size</code>,
        where both <code>style</code> and <code>size</code> are optional.
        """
        self.font = font
        self.tkFont = decodeFont(self.font)
        self.updateProperties(font=self.tkFont)
        self._updateLocation()

# Public method: getFont

    def getFont(self):
        """
        Returns the current font for the GLabel.
        """
        return self.font

# Public method: setLabel

    def setLabel(self, text):
        """
        Changes the string stored within the GLabel object, so that
        a new text string appears on the display.
        """
        self.text = text
        self.updateProperties(text=text)

# Public method: getLabel

    def getLabel(self):
        """
        Returns the string displayed by this object.
        """
        return self.text

# Public method: getAscent

    def getAscent(self):
        """
        Returns the maximum distance strings in this font extend above
        the baseline.
        """
        return self.tkFont.metrics("ascent")

# Public method: getDescent

    def getDescent(self):
        """
        Returns the maximum distance strings in this font descend below
        the baseline.
        """
        return self.tkFont.metrics("descent")

# Override method: getWidth

    def getWidth(self):
        """
        Returns the width for this <code>GLabel</code>.
        """
        return self.tkFont.measure(self.text)

# Override method: getHeight

    def getHeight(self):
        """
        Returns the height for this <code>GLabel</code>.
        """
        return self.tkFont.metrics("linespace")

# Override method: getBounds

    def getBounds(self):
        """
        Returns the bounding rectangle for this object.
        """
        return GRectangle(self.x, self.y - self.getAscent(),
                          self.getWidth(), self.getHeight())

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GLabel"

# Override method: _updateLocation

    def _updateLocation(self):
        """
        Updates the location for this <code>GLabel</code> from the stored
        x and y values.  This override is necessary to adjust for the
        baseline.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        offx = 0
        offy = self.getHeight() - self.getAscent()
        gobj = self.getParent()
        while gobj is not None:
            offx += gobj.x
            offy += gobj.y
            gobj = gobj.getParent()
        dx = (self.x + offx) - coords[0]
        dy = (self.y + offy) - coords[1]
        tkc.move(self.tkid, dx, dy)

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GLabel</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        baseline = y + self.getHeight() - self.getAscent()
        self.tkid = tkc.create_text(x,
                                    baseline,
                                    text=self.text,
                                    font=self.tkFont,
                                    fill=self.color,
                                    anchor="sw")

# Override method: __str__

    def __str__(self):
        return "GLabel(\"" + self.str + "\")"

Ancestors

Class variables

var DEFAULT_FONT

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

Methods

def getAscent(self)

Returns the maximum distance strings in this font extend above the baseline.

Expand source code
def getAscent(self):
    """
    Returns the maximum distance strings in this font extend above
    the baseline.
    """
    return self.tkFont.metrics("ascent")
def getBounds(self)

Returns the bounding rectangle for this object.

Expand source code
def getBounds(self):
    """
    Returns the bounding rectangle for this object.
    """
    return GRectangle(self.x, self.y - self.getAscent(),
                      self.getWidth(), self.getHeight())
def getDescent(self)

Returns the maximum distance strings in this font descend below the baseline.

Expand source code
def getDescent(self):
    """
    Returns the maximum distance strings in this font descend below
    the baseline.
    """
    return self.tkFont.metrics("descent")
def getFont(self)

Returns the current font for the GLabel.

Expand source code
def getFont(self):
    """
    Returns the current font for the GLabel.
    """
    return self.font
def getHeight(self)

Returns the height for this GLabel.

Expand source code
def getHeight(self):
    """
    Returns the height for this <code>GLabel</code>.
    """
    return self.tkFont.metrics("linespace")
def getLabel(self)

Returns the string displayed by this object.

Expand source code
def getLabel(self):
    """
    Returns the string displayed by this object.
    """
    return self.text
def getType(self)

Returns the type of this object.

Expand source code
def getType(self):
    """
    Returns the type of this object.
    """
    return "GLabel"
def getWidth(self)

Returns the width for this GLabel.

Expand source code
def getWidth(self):
    """
    Returns the width for this <code>GLabel</code>.
    """
    return self.tkFont.measure(self.text)
def setFont(self, font)

Changes the font used to display the GLabel as specified by font, which has the form family-style-size, where both style and size are optional.

Expand source code
def setFont(self, font):
    """
    Changes the font used to display the GLabel as specified by
    <code>font</code>, which has the form <code>family-style-size</code>,
    where both <code>style</code> and <code>size</code> are optional.
    """
    self.font = font
    self.tkFont = decodeFont(self.font)
    self.updateProperties(font=self.tkFont)
    self._updateLocation()
def setLabel(self, text)

Changes the string stored within the GLabel object, so that a new text string appears on the display.

Expand source code
def setLabel(self, text):
    """
    Changes the string stored within the GLabel object, so that
    a new text string appears on the display.
    """
    self.text = text
    self.updateProperties(text=text)

Inherited members

class GLine (x0, y0, x1, y1)

This graphical object subclass represents a line segment.

Initializes a line segment from its endpoints. The point (x0, y0) defines the start of the line and the point (x1, y1) defines the end.

Expand source code
class GLine(GObject):
    """
    This graphical object subclass represents a line segment.
    """

# Constructor: GLine

    def __init__(self, x0, y0, x1, y1):
        """
        Initializes a line segment from its endpoints.  The point
        (<code>x0</code>, <code>y0</code>) defines the start of the
        line and the point (<code>x1</code>, <code>y1</code>) defines
        the end.
        """
        GObject.__init__(self)
        self.x = x0
        self.y = y0
        self.dx = x1 - x0
        self.dy = y1 - y0

# Public method: setStartPoint

    def setStartPoint(self, x, y):
        """
        Sets the initial point to (<code>x</code>, <code>y</code>),
        leaving the end point unchanged.  This method is therefore
        different from <code>setLocation</code>, which moves both
        components of the line segment.
        """
        self.dx += self.x - x
        self.dy += self.y - y
        self.x = x
        self.y = y
        self.updatePoints()

# Public method: getStartPoint

    def getStartPoint(self):
        """
        Returns the point at which the line starts.
        """
        return GPoint(self.x, self.y)

# Public method: setEndPoint

    def setEndPoint(self, x, y):
        """
        Sets the end point in the line to (x, y), leaving the start point
        unchanged.
        """
        self.dx = x - self.x
        self.dy = y - self.y
        self.updatePoints()

# Public method: getEndPoint

    def getEndPoint(self):
        """
        Returns the point at which the line ends.
        """
        return GPoint(self.x + self.dx, self.y + self.dy)

# Overload method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        x0 = self.getX()
        y0 = self.getY()
        x1 = x0 + self.dx
        y1 = y0 + self.dy
        tSquared = __LINE_TOLERANCE__ * __LINE_TOLERANCE__
        if dsq(x, y, x0, y0) < tSquared:
            return True
        if dsq(x, y, x1, y1) < tSquared:
            return True
        if x < min(x0, x1) - __LINE_TOLERANCE__:
            return False
        if x > max(x0, x1) + __LINE_TOLERANCE__:
            return False
        if y < min(y0, y1) - __LINE_TOLERANCE__:
            return False
        if y > max(y0, y1) + __LINE_TOLERANCE__:
            return False
        if (x0 - x1) == 0 and (y0 - y1) == 0:
            return False
        d = dsq(x0, y0, x1, y1)
        u = ((x - x0) * (x1 - x0) + (y - y0) * (y1 - y0)) / d
        return dsq(x, y, x0 + u * (x1 - x0), y0 + u * (y1 - y0)) < tSquared

# Override method: getType

    def getType(self):
        """
        Returns the type of this object
        """
        return "GLine"

# Public method: __str__

    def __str__(self):
        return ("GLine(" + str(self.x) + ", " + str(self.y) + ", " +
                str(self.x + self.dx) + ", " + str(self.y + self.dy) + ")")

# Override method: getBounds

    def getBounds(self):
        """
        Returns the bounds of this <code>GLine</code>.
        """
        x0 = min(self.x, self.x + self.dx)
        y0 = min(self.y, self.y + self.dy)
        x1 = max(self.x, self.x + self.dx)
        y1 = max(self.y, self.y + self.dy)
        return GRectangle(x0, y0, x1 - x0, y1 - y0)

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GLine</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        self.tkid = tkc.create_line(x, y, x + self.dx, y + self.dy,
                                    width=self.getLineWidth(),
                                    fill=self.color)

# Private method: updatePoints

    def updatePoints(self):
        """
        Updates the points in the <code>GLine</code>.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        tkc.coords(self.tkid, self.x, self.y,
                   self.x + self.dx, self.y + self.dy)

Ancestors

Methods

def getBounds(self)

Returns the bounds of this GLine.

Expand source code
def getBounds(self):
    """
    Returns the bounds of this <code>GLine</code>.
    """
    x0 = min(self.x, self.x + self.dx)
    y0 = min(self.y, self.y + self.dy)
    x1 = max(self.x, self.x + self.dx)
    y1 = max(self.y, self.y + self.dy)
    return GRectangle(x0, y0, x1 - x0, y1 - y0)
def getEndPoint(self)

Returns the point at which the line ends.

Expand source code
def getEndPoint(self):
    """
    Returns the point at which the line ends.
    """
    return GPoint(self.x + self.dx, self.y + self.dy)
def getStartPoint(self)

Returns the point at which the line starts.

Expand source code
def getStartPoint(self):
    """
    Returns the point at which the line starts.
    """
    return GPoint(self.x, self.y)
def getType(self)

Returns the type of this object

Expand source code
def getType(self):
    """
    Returns the type of this object
    """
    return "GLine"
def setEndPoint(self, x, y)

Sets the end point in the line to (x, y), leaving the start point unchanged.

Expand source code
def setEndPoint(self, x, y):
    """
    Sets the end point in the line to (x, y), leaving the start point
    unchanged.
    """
    self.dx = x - self.x
    self.dy = y - self.y
    self.updatePoints()
def setStartPoint(self, x, y)

Sets the initial point to (x, y), leaving the end point unchanged. This method is therefore different from setLocation, which moves both components of the line segment.

Expand source code
def setStartPoint(self, x, y):
    """
    Sets the initial point to (<code>x</code>, <code>y</code>),
    leaving the end point unchanged.  This method is therefore
    different from <code>setLocation</code>, which moves both
    components of the line segment.
    """
    self.dx += self.x - x
    self.dy += self.y - y
    self.x = x
    self.y = y
    self.updatePoints()
def updatePoints(self)

Updates the points in the GLine.

Expand source code
def updatePoints(self):
    """
    Updates the points in the <code>GLine</code>.
    """
    gw = self.getWindow()
    if gw is None:
        return
    tkc = gw.canvas
    tkc.coords(self.tkid, self.x, self.y,
               self.x + self.dx, self.y + self.dy)

Inherited members

class GMouseEvent (tke)

This class maintains the data for a mouse event.

Creates a new GMouseEvent from the corresponding tkinter event tke.

Expand source code
class GMouseEvent(GEvent):
    """
    This class maintains the data for a mouse event.
    """

# Constructor: GMouseEvent

    def __init__(self, tke):
        """
        Creates a new <code>GMouseEvent</code> from the corresponding
        tkinter event tke.
        """
        self.x = tke.x
        self.y = tke.y

# Public method: getX

    def getX(self):
        """
        Returns the x coordinate of the mouse event.
        """
        return self.x

# Public method: getY

    def getY(self):
        """
        Returns the y coordinate of the mouse event.
        """
        return self.y

# Override method: getSource

    def getSource():
        """
        Returns the source of the mouse event, which is always the
        root window.
        """
        return tkinter._root

Ancestors

Methods

def getSource()

Returns the source of the mouse event, which is always the root window.

Expand source code
def getSource():
    """
    Returns the source of the mouse event, which is always the
    root window.
    """
    return tkinter._root
def getX(self)

Returns the x coordinate of the mouse event.

Expand source code
def getX(self):
    """
    Returns the x coordinate of the mouse event.
    """
    return self.x
def getY(self)

Returns the y coordinate of the mouse event.

Expand source code
def getY(self):
    """
    Returns the y coordinate of the mouse event.
    """
    return self.y
class GObject

This class is the common superclass of all graphical objects that can be displayed on a graphical window. For examples illustrating the use of the GObject class, see the descriptions of the individual subclasses.

Creates a new GObject. The constructor is called only by subclasses.

Expand source code
class GObject(object):
    """
    This class is the common superclass of all graphical objects that can
    be displayed on a graphical window. For examples illustrating the use
    of the <code>GObject</code> class, see the descriptions of the
    individual subclasses.
    """

# Constructor: GObject

    def __init__(self):
        """
        Creates a new <code>GObject</code>.  The constructor is called
        only by subclasses.
        """
        self.x = 0.0
        self.y = 0.0
        self.sf = 1
        self.angle = 0
        self.color = "Black"
        self.lineWidth = 1.0
        self.visible = True
        self.parent = None
        self.tkid = None
        self.gw = None

# Public method: getX

    def getX(self):
        """
        Returns the x-coordinate of the object.
        """
        return self.x

# Public method: getY

    def getY(self):
        """
        Returns the y-coordinate of the object.
        """
        return self.y

# Public method: getLocation

    def getLocation(self):
        """
        Returns the location of this object as a <code>GPoint</code>.
        """
        return GPoint(self.x, self.y)

# Public method: setLocation

    def setLocation(self, x, y):
        """
        Sets the location of this object to the specified point.
        """
        if type(x) is GPoint:
            x, y = x.getX(), x.getY()
        elif type(x) is dict:
            x, y = x.x, x.y
        self.x = x
        self.y = y
        self._updateLocation()

# Public method: move

    def move(self, dx, dy):
        """
        Moves the object on the screen using the displacements
        <code>dx</code> and <code>dy</code>.
        """
        self.setLocation(self.x + dx, self.y + dy)

# Public method: movePolar

    def movePolar(self, r, theta):
        """
        Moves the object on the screen the distance <i>r</i> in the
        direction <i>theta</i>.
        """
        dx = r * math.cos(math.radians(theta))
        dy = -r * math.sin(math.radians(theta))
        self.move(dx, dy)

# Public method: getWidth

    def getWidth(self):
        """
        Returns the width of this object, which is defined to be the width of
        the bounding box.
        """
        return self.getBounds().getWidth()

# Public method: getHeight

    def getHeight(self):
        """
        Returns the height of this object, which is defined to be the height
        of the bounding box.
        """
        return self.getBounds().getHeight()

# Public method: getSize

    def getSize(self):
        """
        Returns the size of the object as a <code>GDimension</code>.
        """
        bounds = self.getBounds()
        return GDimension(bounds.getWidth(), bounds.getHeight())

# Public method: setLineWidth

    def setLineWidth(self, lineWidth):
        """
        Sets the width of the line used to draw this object.
        """
        self.lineWidth = lineWidth
        self.updateProperties(width=lineWidth)

# Public method: getLineWidth

    def getLineWidth(self):
        """
        Returns the width of the line used to draw this object.
        """
        return self.lineWidth

# Public method: setColour

    def setColour(self, color):
        """
        Alternate spelling for <code>setColor</code>.
        """
        self.setColor(color)

# Public method: setColor

    def setColor(self, color):
        """
        Sets the color used to display this object.  The color parameter is
        usually one of the CSS color names.  The color can also be specified
        as a string in the form <code>"#rrggbb"</code> where <code>rr</code>,
        <code>gg</code>, and <code>bb</code> are pairs of hexadecimal digits
        indicating the red, green, and blue components of the color.
        """
        rgb = convertColorToRGB(color)
        self.color = convertRGBToColor(rgb)
        self.updateColor()

# Public method: getColour

    def getColour(self):
        """
        Alternate spelling for <code>getColor</code>.
        """
        return self.getColor()

# Public method: getColor

    def getColor(self):
        """
        Returns the current color as a string in the form
        <code>"#rrggbb"</code>.  In this string, the values <code>rr</code>,
        <code>gg</code>, and <code>bb</code> are two-digit hexadecimal
        values representing the red, green, and blue components.
        """
        return self.color

# Public method: scale

    def scale(self, sf):
        """
        Scales the object by the specified scale factor.
        """
        raise Exception("Not yet implemented")

# Public method: rotate

    def rotate(self, theta):
        """
        Transforms the object by rotating it theta degrees counterclockwise
        around its origin.
        """
        raise Exception("Not yet implemented")

# Public method: setVisible

    def setVisible(self, flag):
        """
        Sets whether this object is visible.
        """
        self.visible = flag
        self.updateVisible()

# Public method: isVisible

    def isVisible(self):
        """
        Returns true if this object is visible.
        """
        return self.visible

# Public method: sendForward

    def sendForward(self):
        """
        Moves this object one step toward the front in the z dimension.
        If it was already at the front of the stack, nothing happens.
        """
        parent = self.getParent()
        if parent is not None:
            parent._sendForward(self)

# Public method: sendToFront

    def sendToFront(self):
        """
        Moves this object to the front of the display in the z dimension.
        By moving it to the front, this object will appear to be on top of the
        other graphical objects on the display and may hide any objects that
        are further back.
        """
        parent = self.getParent()
        if parent is not None:
            parent._sendToFront(self)

# Public method: sendBackward

    def sendBackward(self):
        """
        Moves this object one step toward the back in the z dimension.
        If it was already at the back of the stack, nothing happens.
        """
        parent = self.getParent()
        if parent is not None:
            parent._sendBackward(self)

# Public method: sendToBack

    def sendToBack(self):
        """
        Moves this object to the back of the display in the z dimension.
        By moving it to the back, this object will appear to be behind
        the other graphical objects on the display and may be obscured
        by other objects in front.
        """
        parent = self.getParent()
        if parent is not None:
            parent._sendToBack(self)

# Public method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        if type(x) is GPoint:
            x, y = x.getX(), x.getY()
        elif type(x) is dict:
            x, y = x.x, x.y
        bounds = self.getBounds()
        if bounds is None:
            return False
        return bounds.contains(x, y)

# Public method: getParent

    def getParent(self):
        """
        Returns a pointer to the <code>GCompound</code> that contains this
        object.  Every <code>GWindow</code> is initialized to contain a
        single <code>GCompound</code> that is aligned with the window.
        Adding objects to the window adds them to that <code>GCompound</code>,
        which means that every object you add to the window has a parent.
        Calling <code>getParent</code> on the top-level <code>GCompound</code>
        returns <code>None</code>.
        """
        return self.parent

# Abstract method: getType

    def getType(self):
        """
        Returns the concrete type of the object as a string, as in
        "GOval" or "GRect".
        """
        raise Exception("getType is not defined in the GObject class")

# Abstract method: getBounds

    def getBounds(self):
        """
        Returns the bounding box of this object, which is defined to be the
        smallest rectangle that covers everything drawn by the figure.  The
        coordinates of this rectangle do not necessarily match the location
        returned by <code>getLocation</code>.  Given a <code>GLabel</code>
        object, for example, <code>getLocation</code> returns the
        coordinates of the point on the baseline at which the string begins.
        The <code>getBounds</code> method, by contrast, returns a rectangle
        that covers the entire window area occupied by the string.
        """
        raise Exception("getBounds is not defined in the GObject class")

# Private method: updateProperties

    def updateProperties(self, **options):
        """
        Updates the specified properties of the object, if it is installed
        in a window.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        tkc.itemconfig(self.tkid, **options)

# Private method: _updateLocation

    def _updateLocation(self):
        """
        Updates the location for this object from the stored x and y
        values.  Some subclasses need to override this method.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        offx = 0
        offy = 0
        gobj = self.getParent()
        while gobj is not None:
            offx += gobj.x
            offy += gobj.y
            gobj = gobj.getParent()
        dx = (self.x + offx) - coords[0]
        dy = (self.y + offy) - coords[1]
        tkc.move(self.tkid, dx, dy)

# Private method: updateColor

    def updateColor(self):
        """
        Updates the color properties.  Some subclasses need to override
        this method.
        """
        self.updateProperties(fill=self.color)

# Private method: updateVisible

    def updateVisible(self):
        """
        Updates the visible property.
        """
        if self.visible:
            self.updateProperties(state=tkinter.NORMAL)
        else:
            self.updateProperties(state=tkinter.HIDDEN)

# Private method: getWindow

    def getWindow(self):
        """
        Returns the <code>GWindow</code> in which this <code>GObject</code>
        is installed.  If the object is not installed in a window, this
        method returns <code>None</code>.
        """
        gobj = self
        while (gobj.parent is not None):
            gobj = gobj.parent
        return gobj.gw

# Private abstract method: _install

    def _install(self, target, ctm):
        """
        Installs the object in the target, creating any tkinter objects
        that are necessary.
        """
        raise Exception("_install is not defined in the GObject class")

Subclasses

Methods

def contains(self, x, y)

Returns true if the specified point is inside the object.

Expand source code
def contains(self, x, y):
    """
    Returns true if the specified point is inside the object.
    """
    if type(x) is GPoint:
        x, y = x.getX(), x.getY()
    elif type(x) is dict:
        x, y = x.x, x.y
    bounds = self.getBounds()
    if bounds is None:
        return False
    return bounds.contains(x, y)
def getBounds(self)

Returns the bounding box of this object, which is defined to be the smallest rectangle that covers everything drawn by the figure. The coordinates of this rectangle do not necessarily match the location returned by getLocation. Given a GLabel object, for example, getLocation returns the coordinates of the point on the baseline at which the string begins. The getBounds method, by contrast, returns a rectangle that covers the entire window area occupied by the string.

Expand source code
def getBounds(self):
    """
    Returns the bounding box of this object, which is defined to be the
    smallest rectangle that covers everything drawn by the figure.  The
    coordinates of this rectangle do not necessarily match the location
    returned by <code>getLocation</code>.  Given a <code>GLabel</code>
    object, for example, <code>getLocation</code> returns the
    coordinates of the point on the baseline at which the string begins.
    The <code>getBounds</code> method, by contrast, returns a rectangle
    that covers the entire window area occupied by the string.
    """
    raise Exception("getBounds is not defined in the GObject class")
def getColor(self)

Returns the current color as a string in the form "#rrggbb". In this string, the values rr, gg, and bb are two-digit hexadecimal values representing the red, green, and blue components.

Expand source code
def getColor(self):
    """
    Returns the current color as a string in the form
    <code>"#rrggbb"</code>.  In this string, the values <code>rr</code>,
    <code>gg</code>, and <code>bb</code> are two-digit hexadecimal
    values representing the red, green, and blue components.
    """
    return self.color
def getColour(self)

Alternate spelling for getColor.

Expand source code
def getColour(self):
    """
    Alternate spelling for <code>getColor</code>.
    """
    return self.getColor()
def getHeight(self)

Returns the height of this object, which is defined to be the height of the bounding box.

Expand source code
def getHeight(self):
    """
    Returns the height of this object, which is defined to be the height
    of the bounding box.
    """
    return self.getBounds().getHeight()
def getLineWidth(self)

Returns the width of the line used to draw this object.

Expand source code
def getLineWidth(self):
    """
    Returns the width of the line used to draw this object.
    """
    return self.lineWidth
def getLocation(self)

Returns the location of this object as a GPoint.

Expand source code
def getLocation(self):
    """
    Returns the location of this object as a <code>GPoint</code>.
    """
    return GPoint(self.x, self.y)
def getParent(self)

Returns a pointer to the GCompound that contains this object. Every GWindow is initialized to contain a single GCompound that is aligned with the window. Adding objects to the window adds them to that GCompound, which means that every object you add to the window has a parent. Calling getParent on the top-level GCompound returns None.

Expand source code
def getParent(self):
    """
    Returns a pointer to the <code>GCompound</code> that contains this
    object.  Every <code>GWindow</code> is initialized to contain a
    single <code>GCompound</code> that is aligned with the window.
    Adding objects to the window adds them to that <code>GCompound</code>,
    which means that every object you add to the window has a parent.
    Calling <code>getParent</code> on the top-level <code>GCompound</code>
    returns <code>None</code>.
    """
    return self.parent
def getSize(self)

Returns the size of the object as a GDimension.

Expand source code
def getSize(self):
    """
    Returns the size of the object as a <code>GDimension</code>.
    """
    bounds = self.getBounds()
    return GDimension(bounds.getWidth(), bounds.getHeight())
def getType(self)

Returns the concrete type of the object as a string, as in "GOval" or "GRect".

Expand source code
def getType(self):
    """
    Returns the concrete type of the object as a string, as in
    "GOval" or "GRect".
    """
    raise Exception("getType is not defined in the GObject class")
def getWidth(self)

Returns the width of this object, which is defined to be the width of the bounding box.

Expand source code
def getWidth(self):
    """
    Returns the width of this object, which is defined to be the width of
    the bounding box.
    """
    return self.getBounds().getWidth()
def getWindow(self)

Returns the GWindow in which this GObject is installed. If the object is not installed in a window, this method returns None.

Expand source code
def getWindow(self):
    """
    Returns the <code>GWindow</code> in which this <code>GObject</code>
    is installed.  If the object is not installed in a window, this
    method returns <code>None</code>.
    """
    gobj = self
    while (gobj.parent is not None):
        gobj = gobj.parent
    return gobj.gw
def getX(self)

Returns the x-coordinate of the object.

Expand source code
def getX(self):
    """
    Returns the x-coordinate of the object.
    """
    return self.x
def getY(self)

Returns the y-coordinate of the object.

Expand source code
def getY(self):
    """
    Returns the y-coordinate of the object.
    """
    return self.y
def isVisible(self)

Returns true if this object is visible.

Expand source code
def isVisible(self):
    """
    Returns true if this object is visible.
    """
    return self.visible
def move(self, dx, dy)

Moves the object on the screen using the displacements dx and dy.

Expand source code
def move(self, dx, dy):
    """
    Moves the object on the screen using the displacements
    <code>dx</code> and <code>dy</code>.
    """
    self.setLocation(self.x + dx, self.y + dy)
def movePolar(self, r, theta)

Moves the object on the screen the distance r in the direction theta.

Expand source code
def movePolar(self, r, theta):
    """
    Moves the object on the screen the distance <i>r</i> in the
    direction <i>theta</i>.
    """
    dx = r * math.cos(math.radians(theta))
    dy = -r * math.sin(math.radians(theta))
    self.move(dx, dy)
def rotate(self, theta)

Transforms the object by rotating it theta degrees counterclockwise around its origin.

Expand source code
def rotate(self, theta):
    """
    Transforms the object by rotating it theta degrees counterclockwise
    around its origin.
    """
    raise Exception("Not yet implemented")
def scale(self, sf)

Scales the object by the specified scale factor.

Expand source code
def scale(self, sf):
    """
    Scales the object by the specified scale factor.
    """
    raise Exception("Not yet implemented")
def sendBackward(self)

Moves this object one step toward the back in the z dimension. If it was already at the back of the stack, nothing happens.

Expand source code
def sendBackward(self):
    """
    Moves this object one step toward the back in the z dimension.
    If it was already at the back of the stack, nothing happens.
    """
    parent = self.getParent()
    if parent is not None:
        parent._sendBackward(self)
def sendForward(self)

Moves this object one step toward the front in the z dimension. If it was already at the front of the stack, nothing happens.

Expand source code
def sendForward(self):
    """
    Moves this object one step toward the front in the z dimension.
    If it was already at the front of the stack, nothing happens.
    """
    parent = self.getParent()
    if parent is not None:
        parent._sendForward(self)
def sendToBack(self)

Moves this object to the back of the display in the z dimension. By moving it to the back, this object will appear to be behind the other graphical objects on the display and may be obscured by other objects in front.

Expand source code
def sendToBack(self):
    """
    Moves this object to the back of the display in the z dimension.
    By moving it to the back, this object will appear to be behind
    the other graphical objects on the display and may be obscured
    by other objects in front.
    """
    parent = self.getParent()
    if parent is not None:
        parent._sendToBack(self)
def sendToFront(self)

Moves this object to the front of the display in the z dimension. By moving it to the front, this object will appear to be on top of the other graphical objects on the display and may hide any objects that are further back.

Expand source code
def sendToFront(self):
    """
    Moves this object to the front of the display in the z dimension.
    By moving it to the front, this object will appear to be on top of the
    other graphical objects on the display and may hide any objects that
    are further back.
    """
    parent = self.getParent()
    if parent is not None:
        parent._sendToFront(self)
def setColor(self, color)

Sets the color used to display this object. The color parameter is usually one of the CSS color names. The color can also be specified as a string in the form "#rrggbb" where rr, gg, and bb are pairs of hexadecimal digits indicating the red, green, and blue components of the color.

Expand source code
def setColor(self, color):
    """
    Sets the color used to display this object.  The color parameter is
    usually one of the CSS color names.  The color can also be specified
    as a string in the form <code>"#rrggbb"</code> where <code>rr</code>,
    <code>gg</code>, and <code>bb</code> are pairs of hexadecimal digits
    indicating the red, green, and blue components of the color.
    """
    rgb = convertColorToRGB(color)
    self.color = convertRGBToColor(rgb)
    self.updateColor()
def setColour(self, color)

Alternate spelling for setColor.

Expand source code
def setColour(self, color):
    """
    Alternate spelling for <code>setColor</code>.
    """
    self.setColor(color)
def setLineWidth(self, lineWidth)

Sets the width of the line used to draw this object.

Expand source code
def setLineWidth(self, lineWidth):
    """
    Sets the width of the line used to draw this object.
    """
    self.lineWidth = lineWidth
    self.updateProperties(width=lineWidth)
def setLocation(self, x, y)

Sets the location of this object to the specified point.

Expand source code
def setLocation(self, x, y):
    """
    Sets the location of this object to the specified point.
    """
    if type(x) is GPoint:
        x, y = x.getX(), x.getY()
    elif type(x) is dict:
        x, y = x.x, x.y
    self.x = x
    self.y = y
    self._updateLocation()
def setVisible(self, flag)

Sets whether this object is visible.

Expand source code
def setVisible(self, flag):
    """
    Sets whether this object is visible.
    """
    self.visible = flag
    self.updateVisible()
def updateColor(self)

Updates the color properties. Some subclasses need to override this method.

Expand source code
def updateColor(self):
    """
    Updates the color properties.  Some subclasses need to override
    this method.
    """
    self.updateProperties(fill=self.color)
def updateProperties(self, **options)

Updates the specified properties of the object, if it is installed in a window.

Expand source code
def updateProperties(self, **options):
    """
    Updates the specified properties of the object, if it is installed
    in a window.
    """
    gw = self.getWindow()
    if gw is None:
        return
    tkc = gw.canvas
    tkc.itemconfig(self.tkid, **options)
def updateVisible(self)

Updates the visible property.

Expand source code
def updateVisible(self):
    """
    Updates the visible property.
    """
    if self.visible:
        self.updateProperties(state=tkinter.NORMAL)
    else:
        self.updateProperties(state=tkinter.HIDDEN)
class GOval (a1, a2, a3=None, a4=None)

This graphical object subclass represents an oval inscribed in a rectangular box.

The GOval constructor takes either of the following forms:

   GOval(width, height)
   GOval(x, y, width, height)

If the x and y parameters are missing, the origin is set to (0, 0).

Expand source code
class GOval(GFillableObject):
    """
    This graphical object subclass represents an oval inscribed in
    a rectangular box.
    """

# Constructor: GOval

    def __init__(self, a1, a2, a3=None, a4=None):
        """
        The <code>GOval</code> constructor takes either of the following
        forms:

        <pre>
           GOval(width, height)
           GOval(x, y, width, height)
        </pre>

        If the <code>x</code> and <code>y</code> parameters are missing,
        the origin is set to (0, 0).
        """
        GFillableObject.__init__(self)
        if a3 is None:
            x = 0
            y = 0
            width = a1
            height = a2
        else:
            x = a1
            y = a2
            width = a3
            height = a4
        self.width = width
        self.height = height
        self.setLocation(x, y)

# Public method: setSize

    def setSize(self, width, height=None):
        """
        Changes the size of this oval as specified.
        """
        if type(width) is GDimension:
            width, height = width.getWidth(), width.getHeight()
        self.width = width
        self.height = height
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        tkc.coords(self.tkid, coords[0], coords[1],
                   coords[0] + width, coords[1] + height)

# Public method: setBounds

    def setBounds(self, x, y=None, width=None, height=None):
        """
        Changes the bounds of this rectangle to the specified values.
        """
        if type(x) is GRectangle:
            width, height = x.getWidth(), x.getHeight()
            x, y = x.getX(), x.getY()
        self.setLocation(x, y)
        self.setSize(width, height)

# Override method: getBounds

    def getBounds(self):
        """
        Returns the bounds of this <code>GOval</code>.
        """
        return GRectangle(self.x, self.y, self.width, self.height)

# Override method: contains

    def contains(self, x, y):
        rx = self.width / 2
        ry = self.height / 2
        tx = x - (self.x + rx)
        ty = y - (self.y + ry)
        return (tx * tx) / (rx * rx) + (ty * ty) / (ry * ry) <= 1.0

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GOval"

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GOval</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.x, self.y))
        x = pt.getX()
        y = pt.getY()
        self.tkid = tkc.create_oval(x, y,
                                    x + self.width, y + self.height,
                                    width=self.lineWidth)

        self.updateColor()

# Override method: __str__

    def __str__(self):
        return ("GOval(" + str(self.x) + ", " + str(self.y) + ", " +
                str(self.width) + ", " + str(self.height) + ")")

Ancestors

Methods

def getBounds(self)

Returns the bounds of this GOval.

Expand source code
def getBounds(self):
    """
    Returns the bounds of this <code>GOval</code>.
    """
    return GRectangle(self.x, self.y, self.width, self.height)
def getType(self)

Returns the type of this object.

Expand source code
def getType(self):
    """
    Returns the type of this object.
    """
    return "GOval"
def setBounds(self, x, y=None, width=None, height=None)

Changes the bounds of this rectangle to the specified values.

Expand source code
def setBounds(self, x, y=None, width=None, height=None):
    """
    Changes the bounds of this rectangle to the specified values.
    """
    if type(x) is GRectangle:
        width, height = x.getWidth(), x.getHeight()
        x, y = x.getX(), x.getY()
    self.setLocation(x, y)
    self.setSize(width, height)
def setSize(self, width, height=None)

Changes the size of this oval as specified.

Expand source code
def setSize(self, width, height=None):
    """
    Changes the size of this oval as specified.
    """
    if type(width) is GDimension:
        width, height = width.getWidth(), width.getHeight()
    self.width = width
    self.height = height
    gw = self.getWindow()
    if gw is None:
        return
    tkc = gw.canvas
    coords = tkc.coords(self.tkid)
    tkc.coords(self.tkid, coords[0], coords[1],
               coords[0] + width, coords[1] + height)

Inherited members

class GPoint (x=0, y=0)

This class contains real-valued x and y fields. It is used to represent a location on the graphics plane.

Initializes a point with the specified coordinates.

Expand source code
class GPoint:
    """
    This class contains real-valued x and y fields. It is used to represent
    a location on the graphics plane.
    """

# Constructor: GPoint

    def __init__(self, x=0, y=0):
        """Initializes a point with the specified coordinates."""
        self._x = x
        self._y = y

# Public method: getX

    def getX(self):
        """Returns the x component of the point."""
        return self._x

# Public method: getY

    def getY(self):
        """Returns the y component of the point."""
        return self._y

# Public method: __str__

    def __str__(self):
        """Returns the string representation of a point."""
        return "(" + str(self._x) + ", " + str(self._y) + ")"

# Public method: __eq__

    def __eq__(self, other):
        """Returns a Boolean indicating whether two points are equal."""
        if type(other) is GPoint:
            return self._x == other._x and self._y == other._y
        return False

Methods

def getX(self)

Returns the x component of the point.

Expand source code
def getX(self):
    """Returns the x component of the point."""
    return self._x
def getY(self)

Returns the y component of the point.

Expand source code
def getY(self):
    """Returns the y component of the point."""
    return self._y
class GPolygon

This graphical object subclass represents a polygon bounded by line segments. The GPolygon constructor creates an empty polygon. To complete the figure, you need to add vertices to the polygon using some combination of the methods addVertex, addEdge, and addPolarEdge.

Initializes a new empty polygon at the origin.

Expand source code
class GPolygon(GFillableObject):
    """
    This graphical object subclass represents a polygon bounded by line
    segments.  The <code>GPolygon</code> constructor creates an empty
    polygon.  To complete the figure, you need to add vertices to the
    polygon using some combination of the methods <code>addVertex</code>,
    <code>addEdge</code>, and <code>addPolarEdge</code>.
    """

# Constructor: GPolygon

    def __init__(self):
        """
        Initializes a new empty polygon at the origin.
        """
        GFillableObject.__init__(self)
        self.cx = None
        self.cy = None
        self.vertices = [ ]

# Public method: addVertex

    def addVertex(self, x, y):
        """
        Adds a vertex at (<code>x</code>, <code>y</code>) relative to the
        polygon origin.
        """
        self.cx = x
        self.cy = y
        self.vertices.append(GPoint(x, y))

# Public method: addEdge

    def addEdge(self, dx, dy):
        """
        Adds an edge to the polygon whose components are given by the
        displacements <code>dx</code> and <code>dy</code> from the
        last vertex.
        """
        self.addVertex(self.cx + dx, self.cy + dy)

# Public method: addPolarEdge

    def addPolarEdge(self, r, theta):
        """
        Adds an edge to the polygon specified in polar coordinates.  The
        length of the edge is given by <code>r</code>, and the edge extends
        in direction <code>theta</code>, measured in degrees counterclockwise
        from the +<i>x</i> axis.
        """
        self.addEdge(r * math.cos(theta * math.pi / 180),
                     -r * math.sin(theta * math.pi / 180))

# Public method: getVertices

    def getVertices(self):
        """
        Returns a list of the points in the polygon.
        """
        return self.vertices

# Public method: getBounds

    def getBounds(self):
        """
        Returns the bounding rectangle for this object.
        """
        xMin = 0
        yMin = 0
        xMax = 0
        yMax = 0
        for i in range(len(self.vertices)):
            x = self.vertices[i].getX()
            y = self.vertices[i].getY()
            if i == 0 or x < xMin:
                xMin = x
            if i == 0 or y < yMin:
                yMin = y
            if i == 0 or x > xMax:
                xMax = x
            if i == 0 or y > yMax:
                yMax = y
        x0 = self.getX()
        y0 = self.getY()
        return GRectangle(x0 + xMin, y0 + yMin, xMax - xMin, yMax - yMin)

# Public method: contains

    def contains(self, x, y):
        """
        Returns true if the specified point is inside the object.
        """
        tx = x - self.getX()
        ty = y - self.getY()
        crossings = 0
        n = len(self.vertices)
        if n < 2:
            return False
        if self.vertices[0] == self.vertices[n - 1]:
            n = n - 1
        x0 = self.vertices[0].getX()
        y0 = self.vertices[0].getY()
        for i in range(1, n + 1):
            x1 = self.vertices[i % n].getX()
            y1 = self.vertices[i % n].getY()
            if (y0 > ty) != (y1 > ty):
                if tx - x0 < (x1 - x0) * (ty - y0) / (y1 - y0):
                    crossings = crossings + 1
            x0 = x1
            y0 = y1
        return (crossings % 2 == 1)

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GPolygon"

# Public method: __str__

    def __str__(self):
        return "GPolygon(" + str(len(self.vertices)) + " vertices)"

# Override method: _updateLocation

    def _updateLocation(self):
        """
        Updates the location for this object from the stored x and y
        values.  Some subclasses need to override this method.
        """
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        dx = self.x - coords[0]
        dy = self.y - coords[1]
        tkc.move(self.tkid, dx, dy)

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GPolygon</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        coords = [ ]
        for pt in self.vertices:
            coords.append(pt.getX() + x)
            coords.append(pt.getY() + y)
        self.tkid = tkc.create_polygon(*coords, width=self.lineWidth)
        self.updateColor()

Ancestors

Methods

def addEdge(self, dx, dy)

Adds an edge to the polygon whose components are given by the displacements dx and dy from the last vertex.

Expand source code
def addEdge(self, dx, dy):
    """
    Adds an edge to the polygon whose components are given by the
    displacements <code>dx</code> and <code>dy</code> from the
    last vertex.
    """
    self.addVertex(self.cx + dx, self.cy + dy)
def addPolarEdge(self, r, theta)

Adds an edge to the polygon specified in polar coordinates. The length of the edge is given by r, and the edge extends in direction theta, measured in degrees counterclockwise from the +x axis.

Expand source code
def addPolarEdge(self, r, theta):
    """
    Adds an edge to the polygon specified in polar coordinates.  The
    length of the edge is given by <code>r</code>, and the edge extends
    in direction <code>theta</code>, measured in degrees counterclockwise
    from the +<i>x</i> axis.
    """
    self.addEdge(r * math.cos(theta * math.pi / 180),
                 -r * math.sin(theta * math.pi / 180))
def addVertex(self, x, y)

Adds a vertex at (x, y) relative to the polygon origin.

Expand source code
def addVertex(self, x, y):
    """
    Adds a vertex at (<code>x</code>, <code>y</code>) relative to the
    polygon origin.
    """
    self.cx = x
    self.cy = y
    self.vertices.append(GPoint(x, y))
def getBounds(self)

Returns the bounding rectangle for this object.

Expand source code
def getBounds(self):
    """
    Returns the bounding rectangle for this object.
    """
    xMin = 0
    yMin = 0
    xMax = 0
    yMax = 0
    for i in range(len(self.vertices)):
        x = self.vertices[i].getX()
        y = self.vertices[i].getY()
        if i == 0 or x < xMin:
            xMin = x
        if i == 0 or y < yMin:
            yMin = y
        if i == 0 or x > xMax:
            xMax = x
        if i == 0 or y > yMax:
            yMax = y
    x0 = self.getX()
    y0 = self.getY()
    return GRectangle(x0 + xMin, y0 + yMin, xMax - xMin, yMax - yMin)
def getType(self)

Returns the type of this object.

Expand source code
def getType(self):
    """
    Returns the type of this object.
    """
    return "GPolygon"
def getVertices(self)

Returns a list of the points in the polygon.

Expand source code
def getVertices(self):
    """
    Returns a list of the points in the polygon.
    """
    return self.vertices

Inherited members

class GRect (a1, a2, a3=None, a4=None)

This class represents a graphical object whose appearance consists of a rectangular box.

The GRect constructor takes either of the following forms:

   GRect(width, height)
   GRect(x, y, width, height)

If the x and y parameters are missing, the origin is set to (0, 0).

Expand source code
class GRect(GFillableObject):
    """
    This class represents a graphical object whose appearance consists of
    a rectangular box.
    """

# Constructor: GRect

    def __init__(self, a1, a2, a3=None, a4=None):
        """
        The <code>GRect</code> constructor takes either of the following
        forms:

        <pre>
           GRect(width, height)
           GRect(x, y, width, height)
        </pre>

        If the <code>x</code> and <code>y</code> parameters are missing,
        the origin is set to (0, 0).
        """
        GFillableObject.__init__(self)
        if a3 is None:
            x = 0
            y = 0
            width = a1
            height = a2
        else:
            x = a1
            y = a2
            width = a3
            height = a4
        self.width = width
        self.height = height
        self.setLocation(x, y)

# Public method: setSize

    def setSize(self, width, height=None):
        """
        Changes the size of this rectangle as specified.
        """
        if type(width) is GDimension:
            width, height = width.getWidth(), width.getHeight()
        self.width = width
        self.height = height
        gw = self.getWindow()
        if gw is None:
            return
        tkc = gw.canvas
        coords = tkc.coords(self.tkid)
        tkc.coords(self.tkid, coords[0], coords[1],
                   coords[0] + width, coords[1] + height)

# Public method: setBounds

    def setBounds(self, x, y=None, width=None, height=None):
        """
        Changes the bounds of this rectangle to the specified values.
        """
        if type(x) is GRectangle:
            width, height = x.getWidth(), x.getHeight()
            x, y = x.getX(), x.getY()
        self.setLocation(x, y)
        self.setSize(width, height)

# Override method: getBounds

    def getBounds(self):
        """
        Returns the bounds of this <code>GRect</code>.
        """
        return GRectangle(self.x, self.y, self.width, self.height)

# Override method: getType

    def getType(self):
        """
        Returns the type of this object.
        """
        return "GRect"

# Override method: _install

    def _install(self, target, ctm):
        """
        Installs the <code>GRect</code> in the canvas.
        """
        gw = target
        tkc = gw.canvas
        pt = ctm.transform(GPoint(self.getX(), self.getY()))
        x = pt.getX()
        y = pt.getY()
        self.tkid = tkc.create_rectangle(x, y,
                                         x + self.width, y + self.height,
                                         width=self.lineWidth)
        self.updateColor()

# Override method: __str__

    def __str__(self):
        return ("GRect(" + str(self.x) + ", " + str(self.y) + ", " +
                str(self.width) + ", " + str(self.height) + ")")

Ancestors

Methods

def getBounds(self)

Returns the bounds of this GRect.

Expand source code
def getBounds(self):
    """
    Returns the bounds of this <code>GRect</code>.
    """
    return GRectangle(self.x, self.y, self.width, self.height)
def getType(self)

Returns the type of this object.

Expand source code
def getType(self):
    """
    Returns the type of this object.
    """
    return "GRect"
def setBounds(self, x, y=None, width=None, height=None)

Changes the bounds of this rectangle to the specified values.

Expand source code
def setBounds(self, x, y=None, width=None, height=None):
    """
    Changes the bounds of this rectangle to the specified values.
    """
    if type(x) is GRectangle:
        width, height = x.getWidth(), x.getHeight()
        x, y = x.getX(), x.getY()
    self.setLocation(x, y)
    self.setSize(width, height)
def setSize(self, width, height=None)

Changes the size of this rectangle as specified.

Expand source code
def setSize(self, width, height=None):
    """
    Changes the size of this rectangle as specified.
    """
    if type(width) is GDimension:
        width, height = width.getWidth(), width.getHeight()
    self.width = width
    self.height = height
    gw = self.getWindow()
    if gw is None:
        return
    tkc = gw.canvas
    coords = tkc.coords(self.tkid)
    tkc.coords(self.tkid, coords[0], coords[1],
               coords[0] + width, coords[1] + height)

Inherited members

class GRectangle (x=0.0, y=0.0, width=0.0, height=0.0)

This type contains real-valued x, y, width, and height fields. It is used to represent the bounding box of a graphical object.

Initializes a GRectangle object with the specified fields.

Expand source code
class GRectangle:
    """
    This type contains real-valued x, y, width, and height fields. It is
    used to represent the bounding box of a graphical object.
    """

# Constructor: GRectangle

    def __init__(self, x=0.0, y=0.0, width=0.0, height=0.0):
        """
        Initializes a <code>GRectangle</code> object with the specified
        fields.
        """
        self._x = x
        self._y = y
        self._width = width
        self._height = height

# Public method: getX

    def getX(self):
        """
        Returns the x component of the upper left corner.
        """
        return self._x

# Public method: getY

    def getY(self):
        """
        Returns the x component of the upper left corner.
        """
        return self._y

# Public method: getWidth

    def getWidth(self):
        """
        Returns the width component of the GRectangle.
        """
        return self._width

# Public method: getHeight

    def getHeight(self):
        """
        Returns the width component of the GRectangle.
        """
        return self._height

# Public method: isEmpty

    def isEmpty(self):
        """
        Returns <code>True</code> if the rectangle is empty.
        """
        return self._width <= 0 or self._height <= 0

# Public method: contains

    def contains(self, x, y):
        """
        Returns <code>True</code> if the specified point is inside the
        rectangle.
        """
        if type(x) is GPoint:
            x, y = x.getX(), x.getY()
        elif type(x) is dict:
            x, y = x.x, x.y
        return (x >= self._x and
                y >= self._y and
                x < self._x + self._width and
                y < self._y + self._height)

# Public method: __str__

    def __str__(self):
        return ("(" + str(self._x) + ", " + str(self._y) + ", " +
                str(self._width) + ", " + str(self._height) + ")")

# Public method: __eq__

    def __eq__(self, other):
        if type(other) is GRectangle:
            return (self._x == other._x and
                    self._y == other._y and
                    self._width == other._width and
                    self._height == other._height)
        return False

Methods

def contains(self, x, y)

Returns True if the specified point is inside the rectangle.

Expand source code
def contains(self, x, y):
    """
    Returns <code>True</code> if the specified point is inside the
    rectangle.
    """
    if type(x) is GPoint:
        x, y = x.getX(), x.getY()
    elif type(x) is dict:
        x, y = x.x, x.y
    return (x >= self._x and
            y >= self._y and
            x < self._x + self._width and
            y < self._y + self._height)
def getHeight(self)

Returns the width component of the GRectangle.

Expand source code
def getHeight(self):
    """
    Returns the width component of the GRectangle.
    """
    return self._height
def getWidth(self)

Returns the width component of the GRectangle.

Expand source code
def getWidth(self):
    """
    Returns the width component of the GRectangle.
    """
    return self._width
def getX(self)

Returns the x component of the upper left corner.

Expand source code
def getX(self):
    """
    Returns the x component of the upper left corner.
    """
    return self._x
def getY(self)

Returns the x component of the upper left corner.

Expand source code
def getY(self):
    """
    Returns the x component of the upper left corner.
    """
    return self._y
def isEmpty(self)

Returns True if the rectangle is empty.

Expand source code
def isEmpty(self):
    """
    Returns <code>True</code> if the rectangle is empty.
    """
    return self._width <= 0 or self._height <= 0
class GTimer (gw, fn, delay)

This type implements a timer running in the window. This class supports both one-shot and interval timers.

Expand source code
class GTimer:
    """
    This type implements a timer running in the window.  This class supports
    both one-shot and interval timers.
    """

    def __init__(self, gw, fn, delay):
        self.gw = gw
        self.fn = fn
        self.delay = delay
        self.repeats = False
        self.afterId = None
        gw.timers.append(self)

    def timerTicked(self):
        self.timerStopped = False
        self.fn()
        if self.repeats and not self.timerStopped:
            tkc = self.gw.canvas
            self.afterId = tkc.after(self.delay, self.timerTicked)

    def setRepeats(self, flag):
        self.repeats = flag

    def start(self):
        tkc = self.gw.canvas
        self.afterId = tkc.after(self.delay, self.timerTicked)

    def stop(self):
        if self.afterId is not None:
            tkc = self.gw.canvas
            tkc.after_cancel(self.afterId)
            self.timerStopped = True
            self.afterId = None

Methods

def setRepeats(self, flag)
Expand source code
def setRepeats(self, flag):
    self.repeats = flag
def start(self)
Expand source code
def start(self):
    tkc = self.gw.canvas
    self.afterId = tkc.after(self.delay, self.timerTicked)
def stop(self)
Expand source code
def stop(self):
    if self.afterId is not None:
        tkc = self.gw.canvas
        tkc.after_cancel(self.afterId)
        self.timerStopped = True
        self.afterId = None
def timerTicked(self)
Expand source code
def timerTicked(self):
    self.timerStopped = False
    self.fn()
    if self.repeats and not self.timerStopped:
        tkc = self.gw.canvas
        self.afterId = tkc.after(self.delay, self.timerTicked)
class GWindow (width=500, height=300)

This class represents a graphics window that can contain graphical objects.

The constructor takes either of the following forms:

   GWindow()
   GWindow(width, height)

If the dimensions are missing, the constructor creates a GWindow with a default size.

Expand source code
class GWindow(object):
    """
    This class represents a graphics window that can contain graphical
    objects.
    """

# Public constants

    DEFAULT_WIDTH = 500
    DEFAULT_HEIGHT = 300
    MIN_WAKEUP = 20

# Constructor: GWindow

    def __init__(self, width=DEFAULT_WIDTH, height=DEFAULT_HEIGHT):
        """
        The constructor takes either of the following forms:

        <pre>
           GWindow()
           GWindow(width, height)
        </pre>

        If the dimensions are missing, the constructor creates a
        <code>GWindow</code> with a default size.
        """
        try:
            tk = tkinter._root
            tk.deiconify()
        except AttributeError:
            tk = tkinter.Tk()
            tkinter._root = tk
        self.windowWidth = width
        self.windowHeight = height
        self.tk = tk
        self.tk.protocol("WM_DELETE_WINDOW", self.deleteWindow)
        for w in tk.winfo_children():
            w.destroy()
        self.canvas = tkinter.Canvas(tk, width=width, height=height,
                                     highlightthickness=0)
        try:
            self.canvas.pack()
        except:
            pass
        if spyderFlag:
            def cancelTopmost():
                tk.attributes("-topmost", False)
            tk.attributes("-topmost", True)
            tk.focus_force()
            self.canvas.after(0, cancelTopmost)
        self.canvas.update()
        self.images = { }
        self.timers = [ ]
        self.base = GCompound()
        self.base.gw = self
        self.eventManager = EventManager(self)
        self.setWindowTitle(getProgramName())
        self.eventLoopStarted = False
        self.active = True
        if not spyderFlag:
            atexit.register(self.startEventLoop)

    def __eq__(self, other):
        if type(other) is GWindow:
            return self.canvas is other.canvas
        return False

# Public method: close

    def close(self):
        """
        Deletes the window from the screen.
        """
        self.deleteWindow()

# Public method: eventLoop

    def eventLoop(self):
        """
        Waits for events to happen in the window.
        """
        self.eventLoopStarted = True
        tkinter._root.mainloop()

# Public method: requestFocus

    def requestFocus(self):
        """
        Asks the system to assign the keyboard focus to the window, which
        brings it to the top and ensures that key events are delivered to
        the window.
        """
        tkinter._root.canvas.focus_set()

# Public method: clear

    def clear(self):
        """
        Clears the contents of the window.
        """
        self.base.removeAll()

# Public method: getWidth

    def getWidth(self):
        """
        Returns the width of the graphics window in pixels.
        """
        return self.windowWidth

# Public method: getHeight

    def getHeight(self):
        """
        Returns the height of the graphics window in pixels.
        """
        return self.windowHeight

# Public method: addEventListener

    def addEventListener(self, type, fn):
        """
        Adds an event listener of the specified type to the window.
        """
        self.eventManager.addEventListener(type, fn)

# Public method: repaint

    def repaint(self):
        """
        Schedule a repaint on this window.
        """
        pass

# Public method: setWindowTitle

    def setWindowTitle(self, title):
        """
        Sets the title of the graphics window.
        """
        self.windowTitle = title
        self.tk.title(title)

# Public method: getWindowTitle

    def getWindowTitle(self):
        """
        Returns the title of the graphics window.
        """
        return self.windowTitle

# Public method: add

    def add(self, gobj, x=None, y=None):
        """
        Adds the <code>GObject</code> to the window.  The first parameter
        is the object to be added.  The <code>x</code> and <code>y</code>
        parameters are optional.  If they are supplied, the location of
        the object is set to (<code>x</code>, <code>y</code>).
        """
        self.base.add(gobj, x, y)

# Public method: remove

    def remove(self, gobj):
        """
        Removes the object from the window.
        """
        self.base.remove(gobj)

# Public method: getElementAt

    def getElementAt(self, x, y):
        """
        Returns the topmost <code>GObject</code> containing the
        point (x, y), or <code>None</code> if no such object exists.
        """
        return self.base.getElementAt(x, y)

# Public method: createTimer

    def createTimer(self, fn, delay):
        """
        Creates a new timer object that calls fn after the specified
        delay, which is measured in milliseconds.  The timer must be
        started by calling the <code>start</code> method.
        """
        return GTimer(self, fn, delay)

# Public method: setTimeout

    def setTimeout(self, fn, delay):
        """
        Creates and starts a one-shot timer that calls fn after the
        specified delay, which is measured in milliseconds.  The
        setTimeout method returns the <code>GTimer</code> object.
        """
        timer = GTimer(self, fn, delay)
        timer.start()
        return timer

# Public method: setInterval

    def setInterval(self, fn, delay):
        """
        Creates and starts an interval timer that calls fn after the
        specified delay, which is measured in milliseconds.  The
        setInterval method returns the <code>GTimer</code> object.
        """
        timer = GTimer(self, fn, delay)
        timer.setRepeats(True)
        timer.start()
        return timer

# Public method: pause

    def pause(self, delay):
        """
        Pauses the current thread for the specified delay, which is
        measured in milliseconds.  The pause method periodically checks
        the event queue to update the contents of the window.
        """
        nCycles = delay // GWindow.MIN_WAKEUP
        for i in range(nCycles):
            self.tk.update_idletasks()
            self.tk.update()
            time.sleep(delay / nCycles / 1000)

# Private method: deleteWindow

    def deleteWindow(self):
        """
        Closes the window and exits from the event loop.
        """
        self.active = False
        for timer in self.timers:
            timer.stop()
        tkinter._root.destroy()
        del tkinter._root

# Private method: startEventLoop

    def startEventLoop(self):
        """
        Starts the event loop if it wasn't run explicitly.
        """
        if not self.eventLoopStarted:
            self.eventLoop()

# Private method: _rebuild

    def _rebuild(self):
        """
        Rebuilds the tkinter data structure for the window.  This
        operation is triggered if a global update is necessary.
        """
        self.canvas.delete("all")
        self.base._install(self, SimpleTransform())

Class variables

var DEFAULT_HEIGHT

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

>>> int('0b100', base=0)
4
var DEFAULT_WIDTH

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

>>> int('0b100', base=0)
4
var MIN_WAKEUP

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.

>>> int('0b100', base=0)
4

Methods

def add(self, gobj, x=None, y=None)

Adds the GObject to the window. The first parameter is the object to be added. The x and y parameters are optional. If they are supplied, the location of the object is set to (x, y).

Expand source code
def add(self, gobj, x=None, y=None):
    """
    Adds the <code>GObject</code> to the window.  The first parameter
    is the object to be added.  The <code>x</code> and <code>y</code>
    parameters are optional.  If they are supplied, the location of
    the object is set to (<code>x</code>, <code>y</code>).
    """
    self.base.add(gobj, x, y)
def addEventListener(self, type, fn)

Adds an event listener of the specified type to the window.

Expand source code
def addEventListener(self, type, fn):
    """
    Adds an event listener of the specified type to the window.
    """
    self.eventManager.addEventListener(type, fn)
def clear(self)

Clears the contents of the window.

Expand source code
def clear(self):
    """
    Clears the contents of the window.
    """
    self.base.removeAll()
def close(self)

Deletes the window from the screen.

Expand source code
def close(self):
    """
    Deletes the window from the screen.
    """
    self.deleteWindow()
def createTimer(self, fn, delay)

Creates a new timer object that calls fn after the specified delay, which is measured in milliseconds. The timer must be started by calling the start method.

Expand source code
def createTimer(self, fn, delay):
    """
    Creates a new timer object that calls fn after the specified
    delay, which is measured in milliseconds.  The timer must be
    started by calling the <code>start</code> method.
    """
    return GTimer(self, fn, delay)
def deleteWindow(self)

Closes the window and exits from the event loop.

Expand source code
def deleteWindow(self):
    """
    Closes the window and exits from the event loop.
    """
    self.active = False
    for timer in self.timers:
        timer.stop()
    tkinter._root.destroy()
    del tkinter._root
def eventLoop(self)

Waits for events to happen in the window.

Expand source code
def eventLoop(self):
    """
    Waits for events to happen in the window.
    """
    self.eventLoopStarted = True
    tkinter._root.mainloop()
def getElementAt(self, x, y)

Returns the topmost GObject containing the point (x, y), or None if no such object exists.

Expand source code
def getElementAt(self, x, y):
    """
    Returns the topmost <code>GObject</code> containing the
    point (x, y), or <code>None</code> if no such object exists.
    """
    return self.base.getElementAt(x, y)
def getHeight(self)

Returns the height of the graphics window in pixels.

Expand source code
def getHeight(self):
    """
    Returns the height of the graphics window in pixels.
    """
    return self.windowHeight
def getWidth(self)

Returns the width of the graphics window in pixels.

Expand source code
def getWidth(self):
    """
    Returns the width of the graphics window in pixels.
    """
    return self.windowWidth
def getWindowTitle(self)

Returns the title of the graphics window.

Expand source code
def getWindowTitle(self):
    """
    Returns the title of the graphics window.
    """
    return self.windowTitle
def pause(self, delay)

Pauses the current thread for the specified delay, which is measured in milliseconds. The pause method periodically checks the event queue to update the contents of the window.

Expand source code
def pause(self, delay):
    """
    Pauses the current thread for the specified delay, which is
    measured in milliseconds.  The pause method periodically checks
    the event queue to update the contents of the window.
    """
    nCycles = delay // GWindow.MIN_WAKEUP
    for i in range(nCycles):
        self.tk.update_idletasks()
        self.tk.update()
        time.sleep(delay / nCycles / 1000)
def remove(self, gobj)

Removes the object from the window.

Expand source code
def remove(self, gobj):
    """
    Removes the object from the window.
    """
    self.base.remove(gobj)
def repaint(self)

Schedule a repaint on this window.

Expand source code
def repaint(self):
    """
    Schedule a repaint on this window.
    """
    pass
def requestFocus(self)

Asks the system to assign the keyboard focus to the window, which brings it to the top and ensures that key events are delivered to the window.

Expand source code
def requestFocus(self):
    """
    Asks the system to assign the keyboard focus to the window, which
    brings it to the top and ensures that key events are delivered to
    the window.
    """
    tkinter._root.canvas.focus_set()
def setInterval(self, fn, delay)

Creates and starts an interval timer that calls fn after the specified delay, which is measured in milliseconds. The setInterval method returns the GTimer object.

Expand source code
def setInterval(self, fn, delay):
    """
    Creates and starts an interval timer that calls fn after the
    specified delay, which is measured in milliseconds.  The
    setInterval method returns the <code>GTimer</code> object.
    """
    timer = GTimer(self, fn, delay)
    timer.setRepeats(True)
    timer.start()
    return timer
def setTimeout(self, fn, delay)

Creates and starts a one-shot timer that calls fn after the specified delay, which is measured in milliseconds. The setTimeout method returns the GTimer object.

Expand source code
def setTimeout(self, fn, delay):
    """
    Creates and starts a one-shot timer that calls fn after the
    specified delay, which is measured in milliseconds.  The
    setTimeout method returns the <code>GTimer</code> object.
    """
    timer = GTimer(self, fn, delay)
    timer.start()
    return timer
def setWindowTitle(self, title)

Sets the title of the graphics window.

Expand source code
def setWindowTitle(self, title):
    """
    Sets the title of the graphics window.
    """
    self.windowTitle = title
    self.tk.title(title)
def startEventLoop(self)

Starts the event loop if it wasn't run explicitly.

Expand source code
def startEventLoop(self):
    """
    Starts the event loop if it wasn't run explicitly.
    """
    if not self.eventLoopStarted:
        self.eventLoop()
class SimpleTransform (tx=0.0, ty=0.0, rotation=0.0, sf=1.0)
Expand source code
class SimpleTransform:

    def __init__(self, tx=0.0, ty=0.0, rotation=0.0, sf=1.0):
        self.tx = tx
        self.ty = ty
        self.rotation = rotation
        self.sf = sf

    def getTX(self):
        return self.tx

    def getTY(self):
        return self.ty

    def getRotation(self):
        return self.rotation

    def getSF(self):
        return self.sf

    # Current stub implementation assumes no rotation and scaling

    def transform(self, pt):
        x0 = pt.getX()
        y0 = pt.getY()
        if self.rotation == 0:
            x1 = self.tx + self.sf * x0
            y1 = self.ty + self.sf * y0
        else:
            ct = math.cos(math.radians(self.rotation))
            st = math.sin(math.radians(self.rotation))
            x1 = self.tx + self.sf * (x0 * ct + y0 * st)
            y1 = self.ty + self.sf * (y0 * ct - x0 * st)
        return GPoint(x1, y1)

    def compose(self, transform):
        return SimpleTransform(self.tx + transform.getTX(),
                               self.ty + transform.getTY())

Methods

def compose(self, transform)
Expand source code
def compose(self, transform):
    return SimpleTransform(self.tx + transform.getTX(),
                           self.ty + transform.getTY())
def getRotation(self)
Expand source code
def getRotation(self):
    return self.rotation
def getSF(self)
Expand source code
def getSF(self):
    return self.sf
def getTX(self)
Expand source code
def getTX(self):
    return self.tx
def getTY(self)
Expand source code
def getTY(self):
    return self.ty
def transform(self, pt)
Expand source code
def transform(self, pt):
    x0 = pt.getX()
    y0 = pt.getY()
    if self.rotation == 0:
        x1 = self.tx + self.sf * x0
        y1 = self.ty + self.sf * y0
    else:
        ct = math.cos(math.radians(self.rotation))
        st = math.sin(math.radians(self.rotation))
        x1 = self.tx + self.sf * (x0 * ct + y0 * st)
        y1 = self.ty + self.sf * (y0 * ct - x0 * st)
    return GPoint(x1, y1)