#include "quickdraw.h"at the beginning of the program, right below the header comment. This gives your program access to the Quickdraw library, which contains all the graphics procedures described in this handout.
In order to bring up the Quickdraw drawing window, you must use the function
InitDraw(qDrawWidth, qDrawHeight);where qDrawWidth and qDrawHeight are parameters that tell the function how large to make the quickdraw window. InitDraw(1000, 800) will create a drawing window so large that it fills the entire screen. Usually your programs will invoke InitDraw at the beginning of main(). Once you have initialized the quickdraw window, you are now ready to start drawing things in it.
In Quickdraw, lines, letters, and shapes are all drawn at locations specified by Cartesian (x,y) coordinates. The origin of the Cartesian plane (0,0) is the at the top left corner of the Quickdraw window. The lower right corner has coordinates (qDrawWidth,qDrawHeight). The x coordinate runs from left to right. The y coordinate runs from top to bottom, as shown below.
Anything that is ever initialized has to be terminated when you are done using it. Before the end of main(), you should call
QuitDraw();
which closes the Quickdraw window
Lines: Quickdraw can draw lines with a moving pen that acts much like the Logo turtle. The Quickdraw pen is always invisible (a "hidden" turtle). To move the pen to a specific Cartesian coordinate without drawing a line, use
MoveTo(x_integer, y_integer);The equivalent Logo expression would be pu, setxy(x_integer, y_integer)
To move the pen to a new location and draw a line on the way, use
LineTo(x_integer, y_integer);The equivalent Logo expression would be pd, setxy(x_integer, y_integer)
Remember, both MoveTo and LineTo move the Quickdraw pen to a new location.
Point: A Point in Quickdraw is a Cartesian location defined by two coordinates, an x-coordinate, and a y-coordinate. A Point is a data type, like an integer or a real; before you use a Point variable, it must be declared at the top of a function:
Point nameOfPoint;Then you can set the location of the point by calling the function:
SetPt(Point nameOfPoint, int x_integer, int y_integer);For example, if you wanted to set myPoint to 20, 40, you would call:
SetPt(myPoint, 20, 40)A Point variable can be passed as a parameter just like any other variable. But beware: SetPt does not actually draw anything! It merely sets the value of a variable for later use. To draw a line between two points, use
DrawLine(Point startingPoint, Point endingPoint);Rect: Quickdraw also provides data type called a Rect which corresponds to a rectangular region in the Quickdraw drawing window. Like a Point variable, a Rect variable must be declared at the top of a function before it can be used in that function:
Rect nameOfRect;Once the Rect has been declared, you can set its size and location with
SetRect(Rect nameOfRect, int left, int top, int right, int bottom);For example, to make a rectangle from with the top-left corner at (20, 40) and the lower-right corner at (80, 100), call:
SetRect(myRect, 20, 40, 80, 100);This command defines myRect as a rectangle with its upper left hand corner at the x-y coordinates (left, top) and its lower right hand corner at (right, bottom). Like SetPt, SetRect does not draw anything on the screen. The Rect variable merely defines the location of a "potential" rectangle in the Quickdraw window. However, using this invisible rectangle as a starting point, there are many Quickdraw functions which you can use to make cool shapes in the drawing window.
Rectangles, Ovals, and Arcs: Once a Rect variable has been declared in a function, and set with SetRect, you can use it to draw rectangles with
FrameRect(nameOfRect); /* draws just the rectangle perimeter */You can also inscribe an oval into the invisible rectangle withPaintRect(nameOfRect); /* fills in the rectangle with a color */
FrameOval(nameOfRect); /* draws just the oval circumference */Drawing arcs is a little more tricky. A Quickdraw "arc" is merely an incomplete inscribed oval. The arc is drawn clockwise for a specified number of degrees, from some starting angle. In the Quickdraw drawing window, 0 degrees points "north," towards thetop of the screen; 90 degrees points "east" towards the right side of the screen; 180 degrees points "south" towards the bottom of the screen; and 270 degrees points "west" towards the left side of the screen.PaintOval(nameOfRect); /* draws a filled oval */
FrameArc(nameOfRect, start, degrees); /* draws arc circumference */For example, the arc filled with the diagonal line pattern above could be drawn with PaintArc(nameOfRect, 0, 90); the dot-filled arc could be drawn with PaintArc(nameOfRect, 90, 270).PaintArc(nameOfRect, start, degrees); /* draws a filled arc */
Polygon: For drawing triangles, pentagons, hexagons, octagons, and so on, we will need the Polygon data type. Like Point and Rect variables, Polygon variables must be declared before they can be used:
Polygon nameOfPoly;The first step to setting up the Polygon is to initialize it with CreatePoly():
nameOfPoly = CreatePoly();With that done, you can add the polygon's vertices one by one, by making multiple calls to PolyAddPt():
PolyAddPt(Polygon nameOfPoly, int x_coord1, int y_coord1);etc.PolyAddPt(Polygon nameOfPoly, int x_coord2, int y_coord2);
Once you have added in all the vertices, you can finally draw the Polygon with
FramePoly(Polygon nameOfPoly);Circles: Although you can easily draw a circle by inscribing an oval into a square Rect, Quickdraw also lets you create circles directly:PaintPoly(Polygon nameOfPoly);
FrameCircle(int x_coordinate, int y_coordinate, int radius);Text: Quickdraw allows you to draw letters and numbers directly to the screen with a special function:PaintCircle(int x_coordinate, int y_coordinate, int radius);
DrawCString(string stringToDraw, int x_coord, int y_coord);The bottom-left corner of the first letter in the string will be drawn at (x_coordinate, y_coordinate). Every subsequent letter is drawn just to the right of its predecessor.
Colors: Quickdraw provides eight colors for your drawing pleasure:
whiteColorAll lines, shapes, and strings are drawn in the current drawing color. The current color can be reset with
blackColor
redColor
greenColor
blueColor
magentaColor
cyanColor
yellowColor
SetColor(Colors colorToUse);where Colors is an enumerated data type, which means that it must equal one of the eight colors listed above.
Patterns: For those of you who find the Quickdraw colors gauche, there are also several patterns at your disposal:
whiteTo draw with patterns, you must first use PenPat():
ltGray
gray
dkGray
black
PenPat(Patterns patternToUse);Patterns is another enumerated data type, which can only take on the five values listed above.
LineWidth: Lines can be of varying width. Default line width is 1 (i.e. a single pixel). The line width can be changed with
SetLineWidth(int lineWidth);LineStyle: Lines may be drawn in any of the following styles:
LINE_STYLE__SOLIDThe line style is updated with the following where styleToUse is one of the above:
LINE_STYLE__ON_OFF_DASH
LINE_STYLE__DOUBLE_DASH
SetLineStyle(LineStyles styleToUse);Like Colors and Patterns, LineStyles is an enumerated data type.
Fonts: DrawCString() draws text in the current font. Note that these names have two underscores. There are only four fonts available:
FONT__SMALLThe current font is set with the following where nameOfFont is one of the above:
FONT__MEDIUM
FONT__LARGE
FONT__LARGEST
SetFont(Fonts nameOfFont);You guessed it: Fonts is yet another enumerated data type, which can only take on the four values listed above.
Mouse Clicks: Before you can design your GUI you need tools to tell you something about the state of the mouse. Specifically, you need to figure out when the mouse button has been clicked, and where. To solve the first problem, Quickdraw provides you with a boolean function called
Button();Button() is a strange function. It doesn't take any parameters! Button() evaluates to either TRUE or FALSE, depending on whether or not the user is pressing the mouse button in the Quickdraw window. Once you have determined that the button has been clicked, you need to figure out where the click occurred in the window. You must first declare a Point variable in your function to represent the position of the mouse:
Point theMouse;Now you can set the value of this Point variable to the mouse's current location with a call to
GetMousePt(theMouse);Button() and GetMousePt() may be used independently. That is, you can determine whether or not the user is pressing the mouse button without finding the mouse's current location, using Button() alone; and you can determine the position of the mouse in the Quickdraw window with GetMousePt() at any time, whether the mouse button is currently being pressed, or not.
Usually, though, you will want to write programs that wait for the user to click the mouse and then figure out where that mouse click occurred. To do so, you will want to use the following code:
while(!Button()) ; /* wait until the mouse button is pressed */while is a conditional loop; in this case, it causes the program to wait until the predicate, Button(), is TRUE. That is, it waits until the mouse button has been pressed. You may not understand why two while loops are necessary to capture a single mouse click. But from the perspective of the very, very fast computer, a "single mouse click" looks like someone has been holding down the mouse button for a long, long time. If you don't wait for the mouse button to be released, your program will end up responding as if the mouse button was pressed several times, even though the user only clicked once. If the purpose of this code is still unclear, please see a TA.
while(Button()) ; /* wait until the mouse button is released */
GetMousePt(theMouse); /* save the current location of the mouse */
Buttons: The foundation of any GUI are the regions called "buttons". When the user clicks the mouse on a button, he or she expects something to happen. As the programmer, it's up to you to figure out what the user wants and do it.
In Quickdraw, the easiest way to represent a button is with a Rect variable. Remember to declare the Rect variable at the top of your function..
Rect theButton;Before you can use theButton, you will have to set its size and location with SetRect(). Then it is usually a good idea to draw theButton with FrameRect() or PaintRect(). This isn't essential, but it makes it much easier for the user to find where theButton is! It's probably also a good idea to label theButton, using DrawCString(); this helps the user understand just what theButton is supposed to do.
Now theButton is all set up, but it's just another graphic. How do you make it respond to clicks? The first thing you must do in your code is determine whether or not the user has clicked the mouse button, and where, as described above. Once you have found the location of theMouse, you need to determine whether or not theMouse lies inside theButton you have set up in Quickdraw. If so, you should take some action; otherwise, do nothing.
if(PtInRect(theMouse, theButton))Like Button(), PtInRect() is a boolean function; it returns TRUE if the Point variable lies within the Rect variable, and FALSE otherwise. If theMouse is inside theButton when Button() is TRUE, then the user clicked on the Quickdraw button, and a reprimand is issued. All together, now:
DrawCString("Please do not press this button again!", 100, 400);
void GUI() {Point theMouse;
Rect theButton;
/* I assume Quickdraw was already initialized in main() */
SetRect(theButton, 50, 50, 550, 250); /* set the button's size
and location */
FrameRect(theButton); /* draw box around button */
DrawCString("PANIC", 100, 200); /* label the button */
/* loop until the user clicks on the panic button */
while(!PtInRect(theMouse, theButton)) {
while(!Button()); /* waits for the user to click the mouse button */
while(Button()); /* waits for the user to release the mouse button */
GetMousePt(theMouse); /* saves mouse's location when button was clicked */
/* if the mouse was clicked inside the panic button, exit loop */
}
/* finally, issue the reprimand */
DrawCString("Please do not press this button again!", 100,
400);
}