RLAI Reinforcement Learning and Artificial Intelligence (RLAI)
Reference manual for Gpython 1.0, a python module for low-level device-independent 2D graphics

by Rich Sutton and Steph Schaeffer

This web page is a long one, as its ambition is to be a standalone tutorial and complete reference manual for the first version of the G graphics language to be implemented in python.  This version is based on and requires existent python modules tk and tkinter.  Instructions on downloading and installing Gpython are provided separately.  Other versions of G can be found here.

Definitions:

Python is an open-source programming language that has become popular because it is widely available, simple, high level, interactive, and has a large user community providing extensive addon tools and functionality.  G is an example of such addon functionality.

A module in python is a smallish addon that usually consists of a single file.  G is a module.

A package is a larger python addon that generally consists of several modules.

tkinter is a python package interface to tk, which provides basic graphics and user interface functionality across python implementations.


Introduction

This document describes G, a python module for low-level, interactive graphics programming. G provides a standard set of routines for graphics programming that is easily portable across machines, languages, and graphics devices. The design of G is based on Gus, a graphics package designed by Andrew Cromarty, Richard Sutton and others at the University of Massachusetts in 1981. G is meant to support the simultaneous use of multiple graphical devices. In 2004 G was converted to Python. This document describes the G routines and their use in Python.

G is not intended to be complete nor static. New functionality can easily be added to it. For example, the current specification does not include the ability to draw ovals, but it would be easy to add this, and the current design suggests all the arguments and names for the new routines that would be needed.

Views

All graphical operations in G are done in the context of a special graphical environment (python object) called a view. The view specifies the region of the display to draw into, the coordinate system for drawing, and a variety of other state information pertaining to drawing commands. Typically, a user will have several views open at the same time, each supporting a different way of drawing onto a device. Windows are a special kind of view, and there is one view corresponding to the entire surface of the graphics device (e.g., to the whole screen).

The region of the display corresponding to a view is called the view's viewport. G provides a complete set of viewport routines for altering and examining viewports.

Coordinate Systems

Views support drawing within their viewports in two coordinate systems. The normalized coordinate system permits drawing in floatingPoint coordinates within a range of x and y coordinates specified by the user on a view-by-view basis. Many users will probably operate exclusively with normalized coordinates, but those who wish greater control and efficiency can use the device coordinate system. The device coordinate system uses integer coordinates corresponding to the actual pixels of the graphics device. Use of the two coordinate systems can be freely intermixed, even for the same view.

If one draws over the full range of a view's coordinate system then the result will also cover the full span of the view's viewport. Attempts to draw outside the coordinate system will be "clipped" at the viewport boundary and will not appear on the display.

G provides a complete set of coordinate system routines for setting the normalized coordinate system and for examining the current status of both the normalized and the device coordinate systems.

Hierarchies of Views

It is convenient to organize views into hierarchies. The viewports of child views are in terms of the coordinate systems of the the parent views, and are automatically moved when their parent is moved. In the primary example of this, the parent view is a window and the child views are subregions of the window. It is much easier to specify the viewports of the child views with respect to the window than, say, with respect to the screen as a whole. When the window is moved, the child views naturally move with it.

The viewports of child views are not restricted to lie within the viewports of the parent view, but any portion protruding beyond the parent view will not be visible on the display (it will be clipped).

In G, there is one hierarchy of views for each display device. The root view of each hierarchy is the device itself.

G and the Tk Window System

G treats the window system in Tk as a display device called GDEVICE. This device is the root view and the windows are the first generation child views. Drawing is not permitted directly on the device, but must be through windows. Tk has its own object classes, which are the basis for, but distinct from, G object classes Gview and Gwindow (see figure).

Much of G can be used without learning about its special object classes and routines for setting up views, but using the standard tk objects and routines instead. In this case drawing can only be done in device coordinates, but it will still be simpler than using the tk interface.

Alternatively, G can be used without learning about tk at all, but using entirely G routines instead. One can use G routines instead of tk routines for most operations on windows.

Naming Conventions

All G routines begin with the prefix "g" or "gd". The gd prefix is used for routines that specify coordinates in device coordinates and the g prefix is used otherwise. A suffix convention is used for routines that specify two endpoints, such as gDrawLine. One version of the routine specifies both endpoints in absolute coordinates, while another specifies the second endpoint relatively, by an offset from the first. The relative version of the routine has a suffix of "R". For example, the version of gDrawLine that specifies the second endpoint relative to the first is named "gDrawLineR". This convention is used throughout G, not just for drawing routines.

Routines for specifying and constructing colors to be used for drawing all begin with "gColor". All other G routines are meant to read as imperative commands, i.e., with a verb and object. For example, gSetViewport is the routine directing G to set the viewport of a specified view, and gDrawCircle is the command directing G to draw a circle. This may at first seem a little verbose, but it wears well. All G names are defined in a separate module called "g". All routines that work by side-effect include the word "set" in their names. Wherever the phrase "CoordinateSystem" appears in a routine name it can be abbreviated "CS".

A Complete Example of Using G

In this example a small circle is drawn in the middle of a newly created window:

from g import *
w = Gwindow()
black = gColorBlack(w)
gDrawCircle(w, .5, .5, .1, black)
gMainloop() #or gMakeVisible(w)


G Objects and Object Classes

Here are the major class-subclass relationships in G. This diagram is correct conceptually, but the implementation details may not be exactly as shown.

Gview
The basic class of all G views. Inherits from tk's Canvas class. Mix this into new classes to define your own specialized G views.

Gview([parent])
Return a new G view with parent parent, which must be an existing window or view. If parent is not provided, then it defaults to the frontmost Gwindow. If there are no Gwindows, then it defaults to the frontmost window of any class, typically the listener being typed into. Other initargs accepted by tk's Canvas class can also be provided.

Gwindow
The class of all G windows. Inherits from Gview, and contains a tk Toplevel element. Mix this into new classes to define your own specialized G windows.

Windows are a special class of view in that they appear with a border around them, including a title-bar at the top. The viewport of a window refers to the region inside the border. If you want the border to be visible you must leave extra room for it.

Gwindow([gViewport=(...), gdViewport=(...), gViewportR=(...)=(...), gdViewportR])
Return a new G window on the device given by parent. If one of the viewport arguments is provided it must be a list of four numbers, (x1, y1, x2, y2) or (x, y, deltax, deltay), specifying the initial viewport of the new window as if they had been input to one of the viewport setting routines. At most one viewport argument should be provided. Other initargs accepted by tk's Toplevel class can also be provided. For example:
Gwindow(gViewport=(.5,.5,.75,.75), windowTitle="My Window") 

Gdevice
The class of all G graphics devices. Inherits from Gview.

GDEVICE
This variable is bound to the root view and the graphics device corresponding to the main screen, an instance of Gdevice. (Drawing is not permitted directly on GDEVICE.) All windows are taken to have GDEVICE as their parent. Thus, it is the parent view of all regular Gwindows. It can be passed into coordinate system routines that use normalized coordinates to establish a new coordinate system for positioning windows on the screen. For example, here is how one would establish a coordinate system for positioning windows in inches from the upper left corner of the screen:
gSetCSscale(GDEVICE,0,0,'inches,'inches,'upperLeft)

In tk, the viewport of GDEVICE is always the entire screen, but the first 20 pixels of this are usually obscured by the menubar. Another 18 pixels are needed for window titles. Thus, if you want to make sure a window placed to start at 0,0 in normalized coordinates has its border and title bar within the visible range, you might do:

gSetCSscale(GDEVICE,-1/72,-38/72,'inches,'inches,'upperLeft)
        Multiple screens? Other devices? Yes, yes, but not yet!

GMENU
The menu associated with GDEVICE. This menu can be used as an application wide menu that any window will inherit.

view.gGetParent()
Return the parent of view.

view.gGetChildren()
Return a tuple of the child views ofview.

view.gCloseView()
When you are done using a G view you should close it, causing various bookkeeping operations to be done. In tk, the view's parent disposes of the subview corresponding to the view. If view is a window, it will disappear from the screen.

Coordinate System Routines

G provides a complete set of routines for examining the normalized and device coordinate systems of a view, for setting the normalized coordinate system, and for converting back and forth between device and normalized coordinate systems.

Coordinate systems are specified by two points, together giving the extreme x and y coordinates that will appear within the viewport, plus an indication of the corner of the viewport that will be occupied by the first point. For example, gSetCoordinateSystem(view,0,0,1,1,'lowerLeft) sets the coordinate system for view to run from 0,0 in the lowerLeft corner of the viewport to 1,1 in the upper right. The allowed values for the corner, in all routines, are 'lowerLeft, 'upperLeft, 'lowerRight, and 'upperRight.

The second point that defines a coordinate system can be specified either absolutely or relatively (as an offset with respect to the first point). In the relative case the routine ends with "R". Routines starting with "gd" pertain to (or return coordinates in) the device coordinate system whereas routines starting with "g" pertain to (or return coordinates in) the normalized coordinate system. Thus, the routine gSetCoordinateSystemR is used to set the normalized coordinate system of a view, specifying its second corner point relative to the first. In all coordinate system routines, the phrase "CoordinateSystem" can be abbreviated to just "CS".

Examining the Coordinate Systems

gGetCoordinateSystem(view)
gdGetCoordinateSystem(view)
Return a tuple of five values, x1, y1, x2, y2, corner, describing the current normalized or device coordinate system for view. The coordinate system runs from coordinates x1,y1 to x2,y2, with coordinates x1,y1 occupying the corner of the viewport indicated by corner, which is one of 'lowerLeft, 'upperRight, 'lowerRight, or 'upperLeft. It will always be the case that x1 < x2 and y1 < y2. gGetCoordinateSystem requires that view be a Gview.

gGetCoordinateSystemR(view)
gdGetCoordinateSystemR(view)
Return a tuple of five values, x, y, xSize, ySize, corner, describing the current normalized or device coordinate system for view. The coordinate system runs from coordinates x,y to x+xSize,y+ySize, with coordinates x,y occupying the corner of the viewport indicated by corner, which is one of 'lowerLeft, 'upperRight, 'lowerRight, or 'upperLeft. xSize and ySize will always be positive. gGetCoordinateSystemR requires that view be a Gview.

gGetCSScale(view)
Return a tuple of five values, x, y, xscale, yscale corner, describing the current normalized coordinate system for view. The coordinate system gives the corner of the viewport indicated by corner the coordinates x,y and then increases across the rest of the view according to the scale arguments xscale and yscale. corner is one of 'lowerLeft, 'upperRight, 'lowerRight, or 'upperLeft. The scale parameters are positive floating point numbers giving the scaling in pixels per unit of the normalized coordinate system.

Setting the Normalized Coordinate System

gSetCoordinateSystem(view, x1, y1, x2, y2, corner)
Set the normalized coordinate system for view to run from coordinates x1,y1 to coordinates x2,y2, with the point x1,y1 occupying the corner of the viewport indicated by corner, which should be one of 'lowerLeft, 'upperRight, 'lowerRight, or 'upperLeft. In subsequent calls to g drawing routines using view, the normalization will be performed such that objects drawn to fill the these new coordinates will fill the viewport of the view. (gd coordinate specification is not affected.)

The initial normalized coordinate system for each view is from 0,0 in the lowerLeft corner to 1,1 in the upper right. This could be restored at any time by gSetCoordinateSystem(view,0,0,1,1,'lowerLeft).

gSetCoordinateSystemR(view, x, y, deltax, deltay, corner)
Set the normalized coordinate system for view to run from coordinates x,y to coordinates x+deltax,y+deltay, with the point x,y occupying the corner of the viewport indicated by corner, which should be one of 'lowerLeft, 'upperRight, 'lowerRight, or 'upperLeft. Otherwise, the efect of this routine is the same as discussed above for gSetCoordinateSystem.

gSetCSscale(view, x, y, xscale, yscale, corner)
Set the normalized coordinate system of view to have coordinates x,y in the corner of the viewport indicated by corner, and then increase across the the rest of the view according to the scale arguments xscale and yscale. corner should be one of should be one of 'lowerLeft, 'upperRight, 'lowerRight, or 'upperLeft. The scale parameters should be one of 'inches, 'centimeters, 'pixels, 'points, or a positive number indicating pixels per unit of the normalized coordinate system.

See GDEVICE for an example of how to set use gSetCSscale to set the normalized coordinate system such that windows can henceforth be positioned in inches from the upper left corner of the screen.

Converting Between Device and Normalized Coordinates

gCoordx(view, dx)
gCoordy(view, dx)
Return the normalized coordinate corresponding to the provided device coordinate, with respect to view.

gdCoordx(view, dx)
gdCoordy(view, dx)
Return the device coordinate corresponding to the provided normalized coordinate, with respect to view.

Converting Between Device and Normalized Offsets

gOffsetx(view, dxOffset)
gOffsety(view, dyOffset)
Convert an offset (distance) in device coordinates to the same offset in normalized coordinates, with respect to view. Note that although the arguments are scaled in pixels, they may be reals to prevent round off error.

gOffsetx(view, dxOffset)
gOffsety(view, dyOffset)
Convert an offset (distance) in normalized coordinates to the same offset in device coordinates, with respect to view. Note that although the returned values are scaled in pixels, they will be reals to prevent round off error.

Converting Between the Coordinate Systems of Different Views

gConvertx(fromView, toView, x)
gConverty(fromView, toView, y)
gdConvertx(fromView, toView, x)
gdConverty(fromView, toView, y)
Given an x or y coordinate in the coordinate system of fromView, these routines return the corresponding coordinate in the coordinate system of toView.

Viewport Routines

G provides routines for setting and examining the viewport of each view in both normalized and device coordinates. A view's viewport is always given in terms of a coordinate system of the parent of the view.

Changing the viewport affects subsequent drawing operations. In subsequent drawing, clipping will be to the new viewport (or rather to the portion of it which is viewable and within the parent view's viewport). In addition, in subsequent calls to "g" graphics routines, normalization of the coordinates will also be to the new viewport. Thus, a program that normally fills the entire parent view can be made to use just a portion of it merely by resetting the viewport (provided it uses entirely normalized coordinates). For example, if the parent has the default coordinate system (running from 0 to 1 in both dimensions), then one can use just the upper right quandrant of it by calling gSetViewport(view,.5,.5,1,1).

Changing the viewport normally does not change the coordinate systems in any way. However, it is possible to trigger arbitrary user code whenever the viewport is changed. See the section on Hooks into Viewport Setting.

I'd prefer that changing the viewport did not change the display in any way. However, in the current implementation, using tk views, this does not seem to be possible. Whenever the viewport is changed, any regions uncovered or newly covered will be erased, and then have gDrawView() called on them).

Note: in the tk version of G, if you move a window by dragging it, currently the viewport position is not updated, so the viewport position numbers may not be accurate. The viewport size is always accurate though.

Getting the Viewport

gGetViewport(view)
gdGetViewport(view)
Return a tuple of four values, x1, y1, x2, y2, indicating the current viewport in device coordinates or normalized coordinates, in the coordinate system of the parent of view. It will always be the case that x1 < x2 and y1 < y2. gGetViewport requires that the parent of view be a Gview.

gGetViewportR(view)
gdGetViewportR(view)
Return a tuple of four values, x y xSize ySize, indicating the current viewport in device coordinates or normalized coordinates, in the coordinate system of the parent of view. x and y are the position of the corner of the viewport that has smallest coordinates, and xSize and ySize are the size of the viewport. gGetViewportR requires that the parent of view be a Gview.

Setting the Viewport

gSetViewport(view, x1, y1, x2, y2)
gdSetViewport(view, x1, y1, x2, y2)
Set the viewport for view to the rectangular portion of the display including the pixels x1,y1 and x2,y2, in the normalized or device coordinates of the parent of view. gSetViewport requires that the parent of view be a Gview.

The default viewport after initialization of a view is the full display surface of the parent.

gSetViewportR(view, x, y, deltax, deltay)
gdSetViewportR(view, x, y, deltax, deltay)

Set the viewport for view to the rectangular portion of the display including the pixels x,y and x+deltax,y+deltay, in the normalized or device coordinates of the parent of view. If any of the last four arguments are nil (or not provided) then they default to their values for the current viewport. gSetViewportR requires that the parent of view be a Gview.

Hooks into Viewport Setting

In many applications, viewports can be changed interactively by users, e.g., when they resize or move a window using the mouse. When this is done, user code may need to be run to adjust coordinate systems or to redraw objects. To assist with this sort of programming, G provides hooks into the viewport setting system. The following routines are called whenever the viewport is changed, either interactively by mousing or by user code.

gAcceptNewViewportSize(view)
This method is called whenever the viewport of view is changed in size. The default method does nothing. Users may want to write specialized methods for specialized view or window classes in order to make automatic adjustments whenever the viewport size is changed. For example, instead of having the normalized coordinate system expanding to fill a larger viewport, one may prefer the coordinate system to grow proportionately, to reveal more of the data space. This and other affects can be easily achieved by resetting the coordinate system each time the viewport is changed, e.g., by calls to gSetCSscale. For example, the effect just described can be accomplished as follows:

class FixedScaleWindow (Gwindow):

def gAcceptNewViewportSize(self):
gSetCSscale(window,0,0,'inches,'inches,'upperLeft)
Gwindow.gAcceptNewViewportSize(self)

Now window classes with FixedScaleWindow mixed in will behave as desired.

Consider another example of the use of gAcceptNewViewportSize. Suppose you want the sizes and positions of child views within a window to be relative to the viewport of the window. The natural way to do this is to set up a normalized coordinate system for the window and place the child views within the window using that coordinate system. However, ordinarily all this would get messed up if the window's viewport were changed, because the viewports of the child views would not be readjusted The following code defines a mixin that causes the child views to all be automatically changed as well:


class maintaingViewportsOfChildren (Gview):

def gAcceptNewViewportSize(self):
children = gGetChildren(view)
gViewports = []
for child in children:
gViewports.append(gGetViewport(child))
Gview.gAcceptNewViewportSize(self)
for child, gViewport in zip(children, gViewports):
x1, y1, x2, y2 = gViewport
gSetViewport(child, x1, y1, x2, y2)

Views of this class, or with this class mixed in, will, whenever their viewports are changed, automatically change the viewports of their child views to maintain their positions and sizes in the normalized coordinates of this view. Thus, whenever a view is changed in size, all the child views will be changed proportionately.

gAcceptNewViewportPosition(view)
Similar to the above, this method is called whenever the viewport of view is changed in position (i.e. moved).

Color Specification Routines

G provides several routines for specifying colors, all beginning with "gColor". Each returns a colorCode to be used in drawing routines. ColorCodes(as set by gColorPen) may be specific to the window, and thus a view must be specified whenever constructing a colorCode. Normally, colorCodes are constructed infrequently and then used over and over, but it is also possible to construct a new colorCode each time anything is drawn.

If the device does not support the requested color -- for example, if you ask for a blue color when using a grayscale screen -- then you will get some approximation to the requested color.

In G, one can also set the characteristics of the "pen" as part of the colorCode. The pen specifies various characteristics of tk drawing, which underlies G. These characteristics can be set by the G routine gColorPen, but these effects are entirely device specific.

ColorCodes should not be altered by the user in anyway. The implementation may rely on this.

gColorBlack(view)
gColorWhite(view)
gColorPink view)
gColorRed(view)
gColorOrange(view)
gColorYellow(view)
gColorGreen(view)
gColorDarkGreen(view)
gColorLightBlue(view)
gColorBlue(view)
gColorPurple(view)
gColorBrown(view)
gColorTan(view)
gColorLightGray(view)
gColorGray(view)
gColorDarkGray(view)
gColorMagenta(view)
gColorCyan(view)
gColorFlip(view)
gColorInvisible(view)
gColorOn(view)
gColorOff(view)
All these functions return a color code for view according to the last part of their name. The name "flip" refers to a color that reversibly inverts the color currently on the screen. The color "invisible" draws but does not affect the color of any pixels on the screen. (These and other possibilities can also be constructed via the use of the specific routine gColorPen.) The names off and on have special meaning in conjunction with the gClear drawing command. gClear sets the entire display to the off color, which may be different for different devices. In general, on is the normal drawing color for a device, and off is its opposite, or erasing color.

Currently on is the same as 'black and off is the same as 'white.

For quick and dirty color use, we also provide the following symbols, internal to the G package:

gBlack
gWhite
gPink
gRed
gOrange
gYellow
gGreen
gDarkGreen
gLightBlue
gBlue
gPurple
gBrown
gTan
gLightGray
gGray
gDarkGray
gMagenta
gCyan
gFlip
gInvisible
gOn
gOff

gColorUserPick(view[, *args])
Allows the user to pick the desired color using the standard interactive Macintosh color picker. args can be used to set the initial color and other aspects of the color picker. Note: when this is invoked, you will notice a Python item flashing in your dock. You must click on it to get the color picker to display. We are still working on resolving this.

gColorRGB(view, red, green, blue)
Return a colorCode for view corresponding to the specified red, green, and blue color components, which range from 0 for minimum intensity to 1 for maximum intensity.

gColorRGB255(view, red, green, blue)
Return a colorCode for view corresponding to the specified red, green, and blue color components, which range from 0 for minimum intensity to 255 for maximum intensity.

gColorBW(view, intensity)
Return a colorCode for view for the color specified according to its intensity along a continuum from the off color at intensity=0 to the on color at intensity=1.0. See above for definitions of on and off colors.

gColorPen(view, colorCode, pattern, mode, xSize[, ySize])
Return a new colorCode for view that is like colorCode except that it has pen characteristics as specified by the remaining arguments. colorCode may be a simple color name (string) or object returned by gColorUserPick, gColorRGB, gColorRGB255, or it may be a colorCode object returned by gColorPen.

The pattern is an 8 by 8 bit pattern that acts like the ink of the pen. Currently G is not using the pattern, so all items are drawn as "solid" objects, and there are no dithering effects.

The mode determines the interaction between the pixels being drawn (from pattern) and the pixels already on the display. For example, the drawn pixels could replace them, OR with them, XOR with them, etc. Currently the mode is not being used either, so all pixels replace, or paint over the existing ones.

The last two arguments to gColorPen make the pen xSize pixels wide and ySize pixels tall. This causes lines and other graphical objects drawn with the new color to appear with the new thickness. When the pen size is greater than one, the extra pixels are drawn below and to the right of the usual pixels. Only the xSize is being used.

gSetColor(view, colorcode)
Sets the color information to use when drawing on view to colorcode. The colorcode should be either a simple color, or the object returned by gColorPen.

gFont(view, fontname, fontsize, fontface)
Returns a font object to use when drawing text. The fontname should be a string of the font name (e.g. "Geneva"), fontsize should be an integer size (e.g. 11), and fontface should be a string describing the face desired (e.g. "normal", "bold", "italic", "bold italic").

Drawing Routines

The drawing routines are those G routines that perform a display (or output-buffering) function.

Most drawing routines come in two forms, one prefaced by "g", and the other by "gd". These two forms differ only in the method used to specify spatial coordinates on the display surface. The g routines use normalized realValued coordinates. Many users will probably use exclusively g routines, but for those who wish to have greater control at the pixel level, the gd routines operate in device-dependent integer coordinates corresponding to pixels of the display. Most calls to g routines get quickly translated into calls to gd routines within G. The use of these two kinds of routines can be freely intermixed.

A suffix convention is used for routines that specify two endpoints, such as gDrawLine. One version of the routine specifies both endpoints in absolute coordinates, while another specifies the second endpoint relatively, by an offset from the first. The relative version of the routine has a suffix of "R". For example, the version of gDrawLine that specifies the second endpoint relative to the first is named "gDrawLineR".

Here are some examples of drawing in device coordinates:

The arguments of all the drawing routines are patterned as follows. The first argument is the view within which drawing takes place. The following arguments typically specify the x and y coordinates of the drawing operation. For g routines these are in normalized coordinates. For gd routines, these are in pixel coordinates, and in tk they must be integers. The final argument is an optional colorCode. (Color codes are constructed by the color specification routines.) If a color is not provided (or nil), then the color used is the same as the last color used with the window associated with the view. To establish a current color for drawing without calling an actual drawing routine, use gSetColor.

Not all of tk's abilities are currently available via G routines. Additional routines should be added, patterned after these, as the need for their additional abilities arise.

gClear(view[, color])
Clear the viewport by filling it with color, or with the off color if color is not provided. Under normal circumstances, a display is initialized to the off color, but G itself performs no initialization of display.

gDelete(view, object)
Deletes the drawn object object from view. If object is a list, or a list of lists, it is traversed to the individual items and they are all deleted. The objects are obtained as the results of the drawing routines. If you save the results of those calls, you can delete the items drawn easily.

gMakeVisible(view)
Make the effects of all previously called graphics routines visible in the display for the device associated with view.

gDrawPoint(view, x, y[, color])
Colors the pixel x,y on view. Returns a pointer to this point.

gDrawLine(view, x1, y1, x2, y2[, color])
gdDrawLine(view, x1, y1, x2, y2[, color])
Draw the line segment between and including the pixels x1,y1 and x2,y2. Returns a pointer to the line segment.

gDrawLineR(view, x, y, deltax, deltay[, color])
gdDrawLineR(view, x, y, deltax, deltay[, color])
Draw the line segment between and including the pixels x,y and x+deltax,y+deltay. Returns a pointer to the line segment.

gOutlineRect(view, x1, y1, x2, y2[, color])
gdOutlineRect(view, x1, y1, x2, y2[, color])
Draw a wire-frame or hollow rectangle with one corner at x1,y1 and the other at x2,y2.

gOutlineRectR(view, x, y, deltax, deltay[, color])
gdOutlineRectR(view, x, y, deltax, deltay[, color])
Draw a wire-frame or hollow rectangle with one corner at x,y and the other at x+deltax,y+deltay. Returns a pointer to the rectangle.

Only vertically or horizontally oriented rectangles can be drawn -- arbitrary angles are not possible. A box of dimension zero appears as a single pixel.

gFillRect(view, x1, y1, x2, y2[, color])
gdFillRect(view, x1, y1, x2, y2[, color])
Fill in the rectangular area including the pixels x1,y1 and x2,y2 with color. Returns a pointer to the rectangle.

gFillRectR(view, x, y, deltax, deltay[, color])
gdFillRectR(view, x, y, deltax, deltay[, color])
Fill in the rectangular area including the pixels x,y and x+deltax,y+deltay with color. Returns a pointer to the rectangle.

Only vertically or horizontally oriented rectangles can be drawn -- arbitrary angles are not possible. A rectangle of dimension zero appears as a single pixel.

gFillPolygon(view, color, x1, y1, x2, y2, x3, y3, ...
gdFillPolygon(view, color, x1, y1, x2, y2, x3, y3, ...
Fill in the polygonal area specified by the points x1,y1 x2,y2 x3,y3 ... with color. The area filled is the area inside the points, such that if they are all the same, then nothing is drawn. If color is nil, then it defaults to the last drawn color on the view. There must be at least one point. Returns a pointer to the polygon.

gDrawCircle(view, x, y, radius[, color])
gdDrawCircle(view, x, y, radius[, color])
Draw a circle to the display with its center at x,y and with radius radius. A circle of radius zero will not appear on the display at all. A radius passed to gDrawCircle is interpretted as a distance along the "y" or vertical dimension and the circle size is scaled accordingly. Returns a pointer to the circle.

As currently implemented, this routine will draw circles that are as wide as they are tall as measured in numbers of pixels. Thus, if the aspect ratio of the display is not 1:1, circles will come out as elipses. The shape of the circle is never affected by the coordinate systems associated with view. Note that this can cause different parts of a display to change their positions relative to each other (when using g routines) as a view is mapped to different viewports.

gDrawDisk(view, x, y, radius[, color])
gdDrawDisk(view, x, y, radius[, color])
Draw a disk (i.e., a filled-in circle) to the display with its center at x,y and with radius radius. Otherwise, these routines behave just like the circleDrawing routines above. Returns a pointer to the circle.

gDrawArc(view, x, y, radius, startAngle, angle[, color])
gdDrawArc(view, x, y, radius, startAngle, angle[, color])
Draw an outline arc to the display with its center of rotation at x,y and with radius radius. The arc begins at startAngle degrees and proceeds for angle degrees. Degrees follow the standard mathematical conventions, increasing counterclockwise from zero pointing directly to the right. For example, gDrawArc(view,x,y,radius,180,90,color) draws the outline of a quarter circle in the lower left quadrant. Otherwise, these routines behave similarly to the circleDrawing routines described above. They also return a pointer to the new object.

gDrawWedge(view, x, y, radius, startAngle, angle[, color])
gdDrawWedge(view, x, y, radius, startAngle, angle[, color])
Draw a filled in wedge to the display with its center of rotation at x,y and with radius radius. The wedge begins at startAngle degrees and proceeds for angle degrees. Degrees follow the standard mathematical conventions, increasing counterclockwise from zero pointing directly to the right. For example, gDrawWedge(view,x,y,radius,180,90,color) draws a filled in quarter circle in the lower left quadrant. Otherwise, these routines behave similarly to the circleDrawing routines described above. They also return a pointer to the new object.

gDrawText(view, string, font, x, y[, color])
gdDrawText(view, string, font, x, y[, color])
Write the string of text to view in color color. The lower left corner of the string appears at x,y. Font is a tuple of font description information, e.g., ("Monaco",12,'italic') in tk. You can use gFont to build this object.

In tk, permitted font names include all the fonts installed in your system. The font size is in points from 1 to 127. The font styles should be one or more of the following: 'normal', 'italic', 'bold'. If several of these are provided, they must be in one string (e.g. 'bold italic'). A 'normal' font style implies the absence of other font styles.

gDrawTextCentered(view, string, font, x, y[, color])
gdDrawTextCentered(view, string, font, x, y[, color])
Write the string of text to view in color color. The center of the string appears at x,y. Font is as described above.

gTextHeight(view, string, font)
gdTextHeight(view, string, font)
Return the vertical size of text when drawn to view in font, in either pixels or normalized coordinates. Font is as described above.

gTextWidth(view, string, font)
gdTextWidth(view, string, font)
Return the horizontal size of text when drawn to view in font, in either pixels or normalized coordinates. Font is as described above.

Event Routines

These are routines for responding to events.

gGetCursorPosition(view)
gdGetCursorPosition(view)
NOT IMPLEMENTED in Python. Return a tuple of two values, the current x and y coordinates of the cursor (mouse) in the coordinate system of view. If the cursor is not within the viewport of view, then None is returned.

gClickEventHandler(view, x, y)
gdClickEventHandler(view dx dy)
If you would like your program to be able to respond to mouse clicks within a G view, then you should specialize the Gview class and write a new method for gClickEventHandler or gdClickEventHandler specialized for the new class. That method will be called with the coordinates of the mouse click whenever there is a mouse click within the viewport of a view of that new class. For example, here is how to cause the current mouse coordinates to be printed to the shell window each time the mouse button is clicked within the view:
 class myView (Gview):

def gClickEventHandler (self, x, y):
print x, y

gMouseUpEventHandler(view, x, y)
gdMouseUpEventHandler(view dx dy)
If you would like your program to be able to respond to mouse dragging within a G view, then you should specialize the Gview class and write a new method for gMouseUpEventHandler or gdMouseUpEventHandler specialized for the new class. That method will be called with the coordinates where the mouse was released whenever the mouse button is released in the viewport of a view of that new class. Use this in conjunction with the click event handlers to allow the user to drag objects in the view. For example, here is how to cause an object to be dragged within the view:
 class myView (Gview):

def gClickEventHandler (self, x, y):
self.lastx, self.lasty = x, y
# find object specified at x, y
...
self.curEvent = 'move'

def gMouseUpEventHandler (self, x, y):
if self.curEvent == 'move':
if x != selflastx or y != lasty:
# move object from lastx, lasty to x, y
...
self.curEvent = None

gMotionEventHandler(view, x, y)
gdMotionEventHandler(view dx dy)
If you would like your program to show mouse dragging within a G view, then you should also write a new method for gMotionEventHandler or gdMotionEventHandler. That method will be called with the coordinates along the path of the mouse dragging. Use this in conjunction with the click and mouse up event handlers to allow the user to visibly drag objects in the view. For example:
 class myView (Gview):

def gClickEventHandler (self, x, y):
self.lastx, self.lasty = x, y
# find object specified at x, y
...
self.curEvent = 'move'

def gMouseUpEventHandler (self, x, y):
if self.curEvent == 'move':
if x != selflastx or y != lasty:
# move object from lastx, lasty to x, y
...
self.curEvent = None

def gMotionEventHandler (self, x, y):
if self.curEvent == 'move':
if x != selflastx or y != lasty:
# move object from lastx, lasty to x, y
...

gKeyEventHandler(view, key)
If you would like your program to respond to key presses within a G view, then you should specialize the Gview class and write a new method for gKeyEventHandler. That method will be called with the key name when a key is pressed while that view is active. Key names are: "Left", "Right", "Up", "Down", "Space", "BackSpace", "Delete", "Escape", "Tab", "Shift_L", "Shift_R", "Control_L", "Control_R", "Alt_L", Alt_R", "Return", "A", "a", "1", "F2", etc. For more details, check the tkinter manual, or just make your event handler print the key it got and press keys to see their names. For example, here is how to respond to a space key pressed while in the view:
class myView (Gview):
def gKeyEventHandler (self, key):
if key == "Space":
...

gDrawView(view)
This routine is called each time your view is moved or uncovered from behind other windows, or resized. If you make a specialized form for a subclass of Gview, then you can arrange for the view to to be automatically redrawn when uncovered (or resized). Otherwise, covered and uncovered views are simply blanked out with the off color. For example, suppose you want a black circle on a white background to always appear in your view. This is what you should do:
 class myView (Gview):

def gDrawView(self):
gDrawCircle(self,.5,.5,.2,gColorBlack(view))

def gAcceptNewViewportSize(self):
Gview.gAcceptNewViewportSize(self)
gClear(view)
self.gDrawView() ; complete redrawing on vp changes

Additional Routines Built on G

The following routines follow the argument conventions established for G, and are designed to extend and be compatible with the other G routines. Since they are written "on top of" G, i.e., since they simply call G routines, they are not considered elementary G routines. (Obviously, this division is a bit arbitrary.)

gDrawArrow(view, x1, y1, x2, y2[, color])
gdDrawArrow(view, x1, y1, x2, y2[, color])
Draw an arrow from x1,y1 to x2,y2 on view.

gDrawArrowR(view, x, y, deltax, deltay[, color])
gdDrawArrowR(view, x, y, deltax, deltay[, color])
Draw an arrow from x,y to x+deltax,y+deltay on view.

gDrawArrowhead(view, x1, y1, x2, y2 bodySize headSize[, color])
gdDrawArrowhead(view, x1, y1, x2, y2 bodySize headSize[, color])
Draw an arrow from x1,y1 to x2,y2 with independent control over the size of the main segment of the arrow and the head of the arrow. BodySize is the fraction of the total length between the two endpoints that is filled by the main segment (starting from the head end of the arrow) and headSize is the relative length of the head segments to the distance between the endpoints. For example, just the arrowhead alone could be drawn by setting bodySize=0. As another example, gDrawArrow is implemented as
 def gDrawArrow(view,x1,y1,x2,y2,color=None) 
gDrawArrowhead(view,x1,y1,x2,y2,1,.25,color))

gDrawArrowheadR(view, x, y, deltax, deltay bodySize headSize[, color])
gdDrawArrowheadR(view, x, y, deltax, deltay bodySize headSize[, color])
Draw an arrow from x,y to x+deltax,y+delta with independent control over the size of the main segment of the arrow and the head of the arrow. Otherwise as above.

Control Routines for G

These routines add buttons and menus and invoke the event processing.

gMainloop()
Starts event processing for your application. Your windows will now be displayed and interactive and the buttons and menus available. Updates to the windows will automatically be displayed. Note that after you call this command, nothing after it in your program will be executed. This should be the LAST thing you call.
gMakeVisible(view)
Make the effects of all previously called graphics routines visible in the display for the device associated with view. If you do not need your window to be interactive, this will be enough to display it without calling gMainloop. Your window will not be interactive if you do not start gMainloop, though. You will not be able to close, resize or move the window. On the mac, the spinning color disc will be the cursor you see when you move into the window.

gQuit()
Deletes all Gwindows and stops event processing for your application.

gAddButton(view, text, command, x, y[, background])
gdAddButton(view, text, command, x, y[, background])
Add a button to view at x, y with the specified text on it. When selected, command will be invoked. To make the button look better, background should be specified as the color of the window where the button will be placed. The newly created button is returned so that you can change the cursor for it, if desired, with gSetCursor.

gEnableButton(button)
Makes button active. If the button had been disabled, it is no longer greyed out. Note that when buttons are created they are enabled by default; you only need this to re-enable a button which has been disabled.

gDisableButton(button)
Makes button inactive. The button is greyed out and cannot be invoked by the user.

gSetTitle(vieworbutton, newtitle)
If vieworbutton is a window, the window title is set to newtitle. If it is a button, the button label is set to newtitle.

gSetCursor(view, cursorname)
Use this function if you would like to have the cursor appear in some special form when it moves over the viewport of a G view or a button. The cursorname should be a string containing the name of a tk cursor. Some are 'crosshair', 'cross' (crosshair cursor), 'sizing' (resize handles), 'arrow', 'sb_down_arrow', 'sb_up_arrow', 'sb_left_arrow', 'sb_right_arrow' (various arrows), 'watch', 'plus', 'pencil', 'hand1', 'hand2', 'xterm'.

For example, to make the cross-hairs cursor appear whenever the cursor goes over your view, you would do the following: gSetCursor(myview, 'crosshair')

gAddMenu(parent, menulabel[, menuitems])
Add a menu to parent consisting of the menu items in the list menuitems. If parent is a window, the menu will be added to the menubar for that window. If it is a menu, the new menu will be added as a submenu. The newly created menu is returned by the function so that it can be used as the parent in future calls.

The format of the menu items is as follows:

For example:

 gAddMenu(window, "FA Demo", \ 
[["Init", initDemo], \
['button', "Show Old Line", showoldlines, 1, 0, None], \
["Resolution Higher", setResolutionHigher], \
["Resolution Lower", setResolutionLower], \
'---', \
["Alpha = 1.0", lambda: setAlpha(1.0)]])

If you wish to have the same menu for any window in your application, you can add to the menu associated with GDEVICE. It is called GMENU. For example,

 global GMENU
gAddMenu(GMENU, "File", [["Open", openfile], ["Quit", gQuit]])

will make a small File menu that is inherited by any window you make.

Obtaining and Installing G

G as described herein can be obtained by following instructions here. Move to the directory where you put g, and start Python. Then import G

from g import *

If you have downloaded quickgraph, you can run Python from the directory where you put it and import g with

from quickgraph.g import *

If you have downloaded the RL Toolkit package and installed it as a python module, you can run Python from anywhere and import g with

from RLtoolkit.g import *

You will then have access to all the G routines. Make sure you start up the event processor with gMainloop (or use gMakeVisible) or your windows won't display or be interactive.

Implementation Notes

G is based on the python package Tkinter. As all of our development has been on a Macintosh, and not all of tk is available through Tkinter, and even less on the mac, some things have not been included so far (patterns, modes, button colors, etc). G is still under development and some undesired things may happen. Please let us know if they do.

Examples

Here is a small example:

# eg with gDrawView - try resizing the window!!

from g import *
class MyWindow(Gwindow):
def __init__(self):
Gwindow.__init__(self)
gdSetViewport(self, 10, 30, 300, 500)

def gDrawView(self):
gClear(self, 'blue')
drawThing(self, 'red')

def drawThing(win, color):
gdFillRect(win, 10, 20, 100, 200, color)

w = MyWindow()
gMainloop()

Here is a very small sample program with a button.

from g import *
def drawThing():
global w
gdFillRect(, 10, 20, 100, 200, 'red')

w = Gwindow()
gdSetViewport(w, 10, 30, 300, 500)
gClear(w, 'blue')
gdAddButton(w, "draw", drawThing, 20, 400, 'blue')
gMainloop()

Here is a very small sample program using gMakeVisible instead of gMainloop.

	from g import *
w = Gwindow()
gdSetViewport(w, 10, 30, 300, 500)
gClear(w, 'blue')
gdDrawCircle(w, 100, 100, 50, 'red')
gMakeVisible(w)
Note that you will not be able to resize, move or close the window (since you have not started event processing).

Extend this Page   How to edit   Style   Subscribe   Notify   Suggest   Help   This open web page hosted at the University of Alberta.   Terms of use  1595/0