2.3 Creating and Operating on an Object
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:
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.
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.
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 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.
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.
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.
The following exercises contain a number of interesting small programs that can be written using the Frame class and the simple programming environment.