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 therr
,gg
, andbb
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 theFont.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
returnsNone
.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
returnsNone
.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 eitherstart
orsweep
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
andy
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 andTrue
is filled. If aGArc
is unfilled, the figure consists only of the arc itself. If aGArc
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
GFillableObject
:contains
getColor
getColour
getFillColor
getHeight
getLineWidth
getLocation
getParent
getSize
getWidth
getWindow
getX
getY
isFilled
isVisible
move
movePolar
rotate
scale
sendBackward
sendForward
sendToBack
sendToFront
setColor
setColour
setFillColor
setLineWidth
setLocation
setVisible
updateColor
updateProperties
updateVisible
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
GCompound
:add
contains
getBounds
getColor
getColour
getElement
getElementAt
getElementCount
getHeight
getLineWidth
getLocation
getParent
getSize
getType
getWidth
getWindow
getX
getY
isVisible
move
movePolar
remove
removeAll
rotate
scale
sendBackward
sendForward
sendToBack
sendToFront
setColor
setColour
setLineWidth
setLocation
setVisible
updateColor
updateProperties
updateVisible
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. Thex
andy
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), orNone
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 andTrue
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 formfamily-style-size
, where bothstyle
andsize
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 fromsetLocation
, 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 aGLabel
object, for example,getLocation
returns the coordinates of the point on the baseline at which the string begins. ThegetBounds
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 valuesrr
,gg
, andbb
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. EveryGWindow
is initialized to contain a singleGCompound
that is aligned with the window. Adding objects to the window adds them to thatGCompound
, which means that every object you add to the window has a parent. CallinggetParent
on the top-levelGCompound
returnsNone
.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 thisGObject
is installed. If the object is not installed in a window, this method returnsNone
.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
anddy
.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"
whererr
,gg
, andbb
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
andy
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
GFillableObject
:contains
getColor
getColour
getFillColor
getHeight
getLineWidth
getLocation
getParent
getSize
getWidth
getWindow
getX
getY
isFilled
isVisible
move
movePolar
rotate
scale
sendBackward
sendForward
sendToBack
sendToFront
setColor
setColour
setFillColor
setFilled
setLineWidth
setLocation
setVisible
updateColor
updateProperties
updateVisible
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 methodsaddVertex
,addEdge
, andaddPolarEdge
.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
anddy
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 directiontheta
, 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
GFillableObject
:contains
getColor
getColour
getFillColor
getHeight
getLineWidth
getLocation
getParent
getSize
getWidth
getWindow
getX
getY
isFilled
isVisible
move
movePolar
rotate
scale
sendBackward
sendForward
sendToBack
sendToFront
setColor
setColour
setFillColor
setFilled
setLineWidth
setLocation
setVisible
updateColor
updateProperties
updateVisible
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
andy
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
GFillableObject
:contains
getColor
getColour
getFillColor
getHeight
getLineWidth
getLocation
getParent
getSize
getWidth
getWindow
getX
getY
isFilled
isVisible
move
movePolar
rotate
scale
sendBackward
sendForward
sendToBack
sendToFront
setColor
setColour
setFillColor
setFilled
setLineWidth
setLocation
setVisible
updateColor
updateProperties
updateVisible
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. Thex
andy
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), orNone
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)