2.3 Creating and Operating on an Object


Applying Operations


The operations defined in the public interface of a class may be applied to any object of that class. Continuing with the example of the Frame class, a Frame object can be created and manipulated as follows:

  Frame display("Test Window", 10,20, 100, 200);
   display.MoveTo(50, 50);
   display.Resize(200,200);
   display.DrawText("Really Neat!", 50,50);

Here, a Frame object named display is declared. The Frame constructor method is called implicitly using the arguments provided in the declaration. These constructor arguments create a Frame whose upper left-hand corner is at location (10,20) and whose height and width are 100 and 200, respectively.

Once the display object has been constructed, it may be operated upon. In this example, the display object is first moved to location (50,50) using the MoveTo method and then the Frame is changed to a 200 x 200 square shape using the Resize method. Finally the text "Really Neat!" is written in the Frame at the location (50,50) relative to the upper left-hand corner of the Frame.

Notice that the "." (dot) operator is used to invoke one of the methods of an object. Thus, display.MoveTo(...) means to invoke the MoveTo method on the object display. People programming in object-oriented languages often use phrasing like "ask the display object to move itself" to refer to operations being taken on objects, reflecting the point of view that an object is an entity that is capable of performing certain actions (e.g., a Frame object knows how to move itself to a new location).

The applet below illustrates the effect of executing the code shown above. In this applet the yellow area at the left shows the declaration for a Frame object and three executable statements that operate on this object. The blue area on the right represents the user's screen. When a frame object is created, a red area will appear on the screen, which represents the window that is created by the Frame object and can be manipulated by applying operations to the Frame object.

In this applet you can click on either of the two buttons at the top of the code to perform the statement that is highlighted in red or to reset the applet back to its orginal condition so that you can execute the statement again. Click on any of the statements in the code area to see a more detailed description of that statement's structure, its parameters, and its effects. The line of code does not need to be the highlighted line of code to click on it.

Frame (Version 1) Simulation

This applet illustrates the concepts of object construction and object manipulation using version 1 of the Frame class. The applet is divided by a vertical line into two areas. The left area, labelled "Class Space", contains an icon that represents version 1 of the Frame class. The Frame class icon is the only one which appears in this area in this version of the simulation; later versions will introduce additional classes. The right area, labelled "Object Space", contains icons that represent objects constructed from the Frame class. Many object icons may appear in the Object Space. The same icon is used to represent the Frame class and the Frame objects to visually indicate their relationship. This visual cue is important in later versions of the simulation where there are many classes and the relationship between an object and its class would not otherwise be clearly evident.

A Frame object may be constructed as follows. Move the cursor to the Frame icon in the Class Space and control-click (i.e., hold down the control key while clicking the mouse button). This will case a menu to appear that shows the signature of the Frame's constructor. A second control-click will remove the constructor menu. Subsequent conrol-clicks will toggle the menu between its visible and hidden states. When the constructor menu is visible, click on the menu item and a dialogue box will appear. The dialogue box has one text box at the top to enter the name associated with the object to be constructed (similar to the variable that names the object in a program) and text boxes for each of the construtor arguments. Fill in each of the fields in the dialogue box and press the "Exec" button to construct the object. Two visible actions will occur when the object is constructed. First, an icon for the object will appear in the Object Space part of the applet. This icon will be labelled with the string given as the object's name in the constructor dialogue box. Second, a window will appear whose title, position, and dimensions correspond to those given in the constructor dialogue box. This part of the simulation emphasises that objects are created by using the constructor of a class and that objects correspond to real entities (in this case a visible window). The icon from a Frame object may be repositioned in the Object Space by dragging the icon (placing the cursor over the icon and holding the mouse button down while moving the mouse). The placement of the icon in the object space has no significance (i.e., moving the icon does not move the window corresponding to that icon).

A Frame object may be manipulated as follows. Move the cursor over the Frame icon in the Object Space and control-click to bring up a menu showing each method that can be applied to a Frame object. Clicking on one of the methods in the menu causes a dialogue box to appear. Enter the parameters of the method and click on the "Exec" button to execute the method on the selected object. The control-click toggels the visibility of the menu of methods. To see the mouse events that occur within the window corresponding to a Frame object, shift-click on the object's icon. This activates a small display that shows the current mouse coordinates when the cursor is within the window and the current mouse button state. A Frame object may be deleted by a control-shift-click (clicking while hold down both the control and shift keys) on the Frame object's icon.

The code to generate the objects visible in the Object Space can be seen by performing a control-click operation in the Object Space outside of an object's icon. This action displays a window in which the code is presented in the form required by the simple programming environment.

 

A Simple Programming Environment

Programming with graphical user-interface objects - like objects of the Frame class and others that will be introduced later - involves a programming environment that is qualitatively different from that typically seen in introductory programming courses. The difference in the programming environment is due to the fact that graphical user-interface systems are event-driven or reactive systems, meaning that the system is driven by the occurrence of external events (mouse clicks, clock alarms) to which the system must react. The typical life cycle of an event-driven or reactive system proceeds as follows:

  1. receive notification that an event has occurred
  2. use information about the current state of the system to decide how to react to the event
  3. react to the event by updating the display and changing the system's state information
  4. return and await the next notification.

The program does not read its inputs or control when such inputs occur, it simply reacts to their occurrence. Some simple examples are given below, using objects of the Frame class as an example.

The events in a graphical user-interface system come from two different sources: the user and the hardware clock. In a typical workstation environment the user generates events by moving the mouse, pressing and releasing mouse buttons, or by pressing keys on the keyboard. With other peripheral devices the user might generate events by movements of a joystick, track-ball, or virtual reality devices (gloves, head-mounted displays, etc.). Only mouse events are dealt with in the first, simple programming environment. The hardware clock generates timing events that are needed to create animated components of a user interface. A very simple example of this is blinking text that draws the user's attention to an important part of the interface. For the program to make the text blink, the program must have some idea of the passage of time. A stream or sequence of timer events provides the program with that.

A simple programming environment that is similar to those found in many object-oriented windowing systems (it is very close, in fact, to the basic model used in the Java Abstract Windowing Toolkit) will be used. However, the initial programming environment is not object-oriented itself. As more is learned about object-oriented programming, portions of the environment will be captured in a better object-oriented manner. Eventually, the entire graphical user-interface program will be represented as an application object.

It will be noted that the simple environment lacks a main program. Object-oriented languages, including C++, do have a main program that defines their initial point of execution and, in many programs, the main program is written by the application developer. However, in a graphical user interface application (and in other applications where a complex run-time library is being used), the main program is more often written by the implementor of the run-time library that provides many of the low-level support functions.

The simple programming environment has four procedures contained in a single file named Program.cc that is shown below. The region outside of the procedures is a global scope in which program-wide objects (such as long-lasting Frame objects) can be declared. This global scope can also be used to define variables that denote the current state of the application. The global objects and global variables can be manipulated inside each of the four procedures. Note that this file's name, Program.cc, is purely arbitrary and has no general significance in C++ or in graphical user-interface programming.


Simple Programming Environment
									// This is the file Program.cc#include "Program.h"// include any necessary header files here (e.g., "Frame.h")// define here any global objects or variablesvoid OnStart(void) {}void OnMouseEvent(char *frameName, int x, int y, int buttonState){}void OnTimerEvent(void){}void OnPaint(void){}

The OnStart function is called exactly once. It can be used to initialize any global object and data as well as create the initial display that the user sees. The OnPaint method is called whenever the system suspects that the user's display may have been damaged and should be redrawn. Common actions that trigger this function being called are a window being moved, resized, or exposed to view after being partially, or completely, obscured by an overlapping window. Whenever, within the display area of a Frame object, the user clicks a mouse button or moves the mouse, the OnMouseEvent function is called. This function has input parameters giving the name of the Frame object in which the event occurred, the x and y coordinates of the mouse's current location, and the condition of the mouse buttons. The OnTimerEvent function is called whenever a clock alarm occurs. The role of each of the four functions in the simple programming environment is briefly summarized in the table below.


Summary of Functions
in Simple Programming Environment
OnStart initialize global objects, global
variables, and the user display
OnPaint redraw the user display when needed
OnTimerEvent react to a clock alarm
OnMouseEvent react to mouse clicks and/or mouse movement

For two reasons, global variables are used in the simple programming environment despite the fact that this seems to contradict the usual (and usually strong and correct) advice to avoid the use of global data. First, the global variables are a temporary expedient - as more is learned about object-oriented programming much, if not all, of the global data will disappear. For the moment, the global data will be tolerated so that experimenting with basic object-oriented ideas can begin. Second, global objects are somewhat less objectionable than global data. At least the object defines an interface that protects its encapsulated data from obvious misuse. Global data has no such protections. Furthermore, in building an association of objects it is not always possible to remove all global data. The objects that form the association sometimes must be defined as global data. By analogy, if an automobile is viewed as an association, it is not possible to conceal some of its constituent parts, such as the steering wheel, the brakes, and the turn signals.

A program is written in the simple programming environment by providing code for some, or all, of the the four functions defined in the simple programming environment and creating an executable program that uses your definitions of these functions. Providing the code for the four functions is done by editing the file Program.cc. This file must then be compiled and linked with the appropriate run-time libraries. This mechanical step is automated by a " make " file that is provided. After editing Program.cc, simply type the command "make," with no arguments. The make program will create an executable file named "Program". For simplicity, the names Program.cc and Program cannot be changed.

When executed, programs developed in the simple programming environment first display a Start window that provides controls for initiating the program, terminating the program, and controlling a simple timer. The Start window is shown in the figure below. When depressed, the Start button will cause the OnStart function to be called, after which the Start button will disappear. At any time, the entire program can be terminated by selection of the Quit item in the File menu. The Timer menu contains two items for turning on and off a timer (a source of clock alarms). The occurrence of a clock alarm will cause the OnTimerEvent function to be called. The interval of this timer (the duration between alarms) is controlled by the slider bar labelled "Timer Control." The slider and the timer are calibrated in milliseconds. The initial slider setting is at 500 milliseconds (one half of one second). The range of timer settings is between 50 milliseconds (one twentieth of one second) and 1000 milliseconds (one second). When the timer is running, its interval can only be changed by stopping the clock, changing the slider position, and then restarting the timer. Changing the slider while the clock is running will not change the timer interval.


The Start Window

Sample Programs


Three simple programs are presented that illustrate the simple programming environment. The first program is a simple "Hello World" program, the second modifies the "Hello World" program to include the handling of mouse button clicks, and the third adds to the second program the use of timer events.

The Hello World program is shown in the table below. This program includes "Frame.h" because it uses the Frame class definition to declare a Frame object named window located at position (200,200) on the display and is 400 pixels wide and 400 pixels tall. This window will have a title of "Hello World Program" when it appears on the display. Both the OnStart and the OnPaint functions clear the window object and write the string "Hello World" near the upper left-hand corner of the window.


Hello World Program
									#include "Frame.h"Frame window("Hello World Program", 200, 200, 400, 400);void OnStart(void) {window.Clear();window.DrawText("Hello World!", 20, 20);}void OnMouseEvent(char *frameName, int x, int y, int buttonState){}void OnTimerEvent(void){}void OnPaint(void){window.Clear();window.DrawText("Hello World!", 20, 20);}

The second program shows how to handle mouse events. In this version of the Hello World program, the string "Hello World!" is written wherever in the window the user clicks the left mouse button. The OnMouseEvent function is called whenever the mouse is moved or a mouse button is clicked. In this program, the OnMouseEvent function checks to see if the state of the mouse buttons indicates that the left mouse button is "down" (i.e., depressed). If the button is down (signalling that the user clicked the mouse button), the window is cleared and the string "Hello World!" is written at the coordinates of the mouse event. The "buttonState" parameter to the OnMouseEvent function is treated as a bit map. The code

       if( buttonState & leftButtonDown)...

simply tests if the bit corresponding to the left button being down is set. If the bit is set, then the mouse button is down. The item "leftButtonDown" is a value defined in an enumeration given in the file Program.h. Other values are rightButtonDown, middleButtonDown, and isDragging. Also important in this program is the use of state information represented by the variables lastx and lasty that record the position of the last place where the "Hello World!" string was written. It is necessary to keep track of this state information so that the OnPaint function will know where in the window the string should be placed when the window needs to be redrawn. Notice that lastx and lasty are initialized in the OnStart function and updated in the OnMouseEvent function whenever a mouse click is recognized.


Hello World Program with Mouse Events
									#include "Program.h"#include "Frame.h"Frame window("Hello World Program", 200, 200, 400, 400);int lastx;int lasty;void OnStart(void) {window.Clear();window.DrawText("Hello World!", 20,20);lastx = 20;lasty = 20;}void OnMouseEvent(char *frameName, int x, int y, int buttonState){if (buttonState & leftButtonDown) {window.Clear();window.DrawText("Hello World!",x,y);lastx = x;    lasty = y;}}void OnTimerEvent(void){}void OnPaint(void){window.Clear();window.DrawText("Hello World!", lastx, lasty);}

The third program illustrates how timer events (clock alarms) are handled. In this program the "Hello World!" string is turned into blinking text by alternately clearing and writing the string on successive timer events. The rate of blinking is controlled by the timer interval. Remember that the timer events will not occur until the timer is turned on using the Timer menu in the Start window. Also remember that the slider bar in the Start window controls the interval between timer events.

The program uses additional state information, given by the variable visible, to record whether the string is or is not visible at the current time. In addition to the OnTimerEvent, the OnMouseEvent and OnPaint functions use this state information to decide whether or not to write the string of text in the window.


Hello World Program with Mouse and Timer Events
									#include "Program.h"#include "Frame.h"Frame window("Hello World Program", 200, 200, 400, 400);int lastx;int lasty;int visible;void OnStart(void) {window.Clear();window.DrawText("Hello World!", 20, 20);lastx = 20;lasty = 20;visible = 1; }void OnMouseEvent(char *frameName, int x, int y, int buttonState){if (buttonState & leftButtonDown) {window.Clear();if (visible)  window.DrawText("Hello World!",x,y);lastx = x;    lasty = y;}}void OnTimerEvent(void){window.Clear();if (visible) visible = 0;else { visible = 1;     window.DrawText("Hello World!", lastx, lasty);   }}void OnPaint(void){window.Clear();if (visible) window.DrawText("Hello World!", lastx, lasty);}

The following exercises contain a number of interesting small programs that can be written using the Frame class and the simple programming environment.

 

Tasks

  1. Write a declaration that creates a Frame object at location (20,30) with a width of 150 and a height of 175.
  2. Write a segment of code to move the Frame you created in the step above to location (50,50) and change its size to a width of 100 and a height of 200.
  3. Write a program that displays your full name approximately centered in a Frame that is itself approximately centered on the screen. Note that you may have to do some experimentation with the sizes and locations.
  4. Write a program that draws a circle of radius 20 in each corner of a Frame of size 400 x 400.
  5. Analog Clock: Write a program that draws a picture of an analog clock in a Frame. A circle can be used for the clock face and a single lines can be used to draw one hand on the clock. Place the hand pointing straight up.

  6. Two-Handed Analog Clock: Modify the Analog Clock program so that it has both a shorter (hours) hand and a longer (minutes) hand. Place the hands so that the time on the clock reads three o'clock.

  7. Analog Clock with Numbers: Modify the Analog Clock program so that the numbers 1 through 12 appear around the outside of the clock face.

  8. Animated Analog Clock: Modify one of the Analog Clock programs so that the hand(s) move. On each timer event move the hand(s) to the next position.

  9. Corner Tour: Write a program that places a circle in the upper left corner of a Frame. The program should then move this circle to the upper right, lower right, and lower left corners before returning the circle to its original position. Repeat this cycle ten times. At each position, display in the window a line of text appropriate for the current position of the window, such as "Upper Left," Upper Right," "Lower Right," "Lower Left."

  10. Border Walk: Write a program that moves a circle in small steps around the outside border of the screen starting from an initial location in the upper left hand corner of the screen. Can you make the motion appear smooth?



©1998 Prentice-Hall, Inc.
A Simon & Schuster Company
Upper Saddle River, New Jersey 07458

Legal Statement