We learned earlier how to handle events and how to use layout managers.These two topics form the basis for the design and implementation of a Graphical User Interface (GUI).
Now we are learning about the various components that we can combine with layout and event handling to produce an effective Graphical User Interface.
The available components are defined by classes in the package java.awt. Our approach is to group those classes into categories and study the material on a category basis. As of this writing, the remaining categories are:
java.lang.Object | +----java.awt.Component | +----java.awt.Canvas |
"A Canvas component represents a blank rectangular area of the
screen onto which the application can draw or from which the application
can trap input events from the user.
An application must subclass the Canvas class in order to get useful functionality such as creating a custom component. The paint method must be overridden in order to perform custom graphics on the canvas." |
"The Canvas class exists to be subclassed. It does nothing on its own; it merely provides a way for you to implement a custom Component. For example, Canvases are useful as display areas for images and custom graphics, whether or not you wish to handle events that occur within the display area." |
"When implementing a Canvas subclass, take care to implement the minimumSize() and preferredSize() methods to properly reflect your canvas's size. Otherwise, depending on the layout your canvas's container uses, your canvas could end up too small -- perhaps even invisible." |
In summary, a Canvas object emulates its namesake in the art world. It provides a workspace on which you can draw or paint.
However, unlike its namesake in the art world, it also provides a surface on which you can recognize events.
The two methods of the class are as follows:
addNotify() Creates the peer of the canvas. paint(Graphics) This method is called to repaint this canvas. |
It also illustrates the ability to instantiate listener objects that can manipulate the source objects on which they are registered without the requirement to pass references to those source objects when the listener objects are instantiated.
Thus, no parameterized constructors are used in the instantiation of listener objects in this program.
When the program first appears on the screen, four non-functionalButton objects and a green Canvas object appear in a Frame object. The objects are separated by horizontal and vertical gaps of thirty pixels. The Button objects are provided simply to cause the Frame object to contain something other than the Canvas object.
The four Button objects are placed at the borders of the Frame object using the BorderLayout manager. The Canvas object is placed in the Center of the Frame object. As mentioned earlier, the BorderLayout manager fills all the available space with the object in the Center and therefore, the preferredSizeand minimumSize parameters weren't a consideration in this program.
When you click on the green Canvas object, the coordinates of the mouse pointer are displayed on that object. If you have studied earlier lessons in this tutorial, you will recognize this program to be very similar to an earlier program where the coordinates of a mouse click were displayed in the client area of a Frame object. The main difference is that in the earlier program, the Frame object itself was the source of the mouse events, and in this program, a Canvas object that is placed in a Frame object is the source for mouse events.
No listener objects were registered for the Frame object or for any of the Button objects. Therefore, clicking in the gaps or clicking on the buttons has no effect on the program.
Clicking on the close button on the Frame object terminates the program and returns control to the operating system.
These results were produced using JDK 1.1.3, running under Windows 95.
The first interesting code fragment in this version of the program is
the code in which we subclass the Canvas class in order to override
the Paint method, and also to cause the object to be green when
it is first instantiated.
class MyCanvas extends Canvas{ int clickX; int clickY; public MyCanvas(){//constructor this.setBackground(Color.green); }//end constructor //Override the paint() method. public void paint(Graphics g){ g.drawString( "" + clickX + ", " + clickY, clickX, clickY); }//end paint() }//end class MyCanvas |
//Create a border layout with gaps. BorderLayout myLayout = new BorderLayout(); myLayout.setVgap(30); myLayout.setHgap(30); this.setLayout(myLayout);//Apply layout to the Frame object |
MyCanvas myCanvasObject = new MyCanvas(); this.add(myCanvasObject,"Center"); |
The next interesting code fragment instantiates and registers a Listener object which will process mouse events to determine and display the coordinates when the user presses the mouse button on the MyCanvas object.
Note that the Listener object is instantiated anonymously and no reference
to the MyCanvas object is passed to the constructor for the Listener
object. Therefore, the listener object must identify the component
on which to display coordinate information from within its own code. We
will see later that the identification is based on the MouseEvent
object that is passed to the event listener when the event occurs.
myCanvasObject.addMouseListener(new MouseProc()); |
This version uses the getComponent() method on the incoming MouseEvent
object to identify the component that was the source of the
event. This method returns a reference to an object of type Component
which must be downcast to type MyCanvas before it can be used to
access the instance variables of an object of type MyCanvas.
class MouseProc extends MouseAdapter{ //Override the mousePressed method public void mousePressed(MouseEvent e){ //Get x and y coordinates of the mouse pointer and // store in the instance variables of the MyCanvas // object. ((MyCanvas)e.getComponent()).clickX = e.getX(); ((MyCanvas)e.getComponent()).clickY = e.getY(); //display coordinate information e.getComponent().repaint(); }//end mousePressed() }//end class MouseProc |
/*File Canvas01.java Copyright 1997, R.G.Baldwin Illustrates the use of the Canvas class. Also illustrates the ability to instantiate listener objects that can manipulate the source objects on which they are registered without the requirement to pass references to those source objects when the listener objects are instantiated. No parameterized constructors are used in the instantiation of listener objects in this program. When the program first appears on the screen, four non- functional buttons and a green Canvas object appear in a Frame object. The objects are separated by horizontal and vertical gaps of thirty pixels. The four buttons are placed at the borders of the Frame object using the BorderLayout manager. The Canvas object is placed in the Center of the Frame object. When you click on the green Canvas object, the coordinates of the mouse pointer are displayed. Clicking in the gaps or clicking on the buttons has no effect on the program. Clicking on the close button on the Frame object terminates the program and returns control to the operating system. These results were produced using JDK 1.1.3, running under Windows 95. */ //=======================================================// import java.awt.*; import java.awt.event.*; //=======================================================// //Subclass Canvas in order to override the paint method // and to make it green when instantiated. class MyCanvas extends Canvas{ int clickX; int clickY; public MyCanvas(){//constructor this.setBackground(Color.green); }//end constructor //Override the paint() method. public void paint(Graphics g){ g.drawString( "" + clickX + ", " + clickY, clickX, clickY); }//end paint() }//end class MyCanvas //=======================================================// class Canvas01 extends Frame{//controlling class public static void main(String[] args){ //instantiate an object of this type new Canvas01(); }//end main public Canvas01(){//constructor //Create a border layout with gaps. BorderLayout myLayout = new BorderLayout(); myLayout.setVgap(30); myLayout.setHgap(30); this.setLayout(myLayout);//Apply layout to the Frame this.setTitle("Copyright 1997, R.G.Baldwin"); this.setSize(300,300); //Instantiate a green customized Canvas object MyCanvas myCanvasObject = new MyCanvas(); //Add the MyCanvas object to the center of the // Frame object. this.add(myCanvasObject,"Center"); //Add four nonfunctional buttons to the borders // of the Frame object this.add(new Button("North"),"North"); this.add(new Button("South"),"South"); this.add(new Button("East"),"East"); this.add(new Button("West"),"West"); this.setVisible(true);//make it all visible //Instantiate and register Listener object which will // terminate the program when the user closes the // Frame. WProc1 winProcCmd1 = new WProc1(); this.addWindowListener(winProcCmd1); //Instantiate and register Listener object which will // process mouse events to determine and display the // coordinates when the user presses the mouse button // on the MyCanvas object. // Note that the Listener object is instantiated // anonymously and no reference to the MyCanvas object // is passed to the constructor for the Listener // object. myCanvasObject.addMouseListener(new MouseProc()); }//end constructor }//end class Canvas01 definition //=======================================================// //This listener class monitors for mouse presses and // displays the coordinates of the mouse pointer when the // mouse is pressed on the object for which it is // registered. class MouseProc extends MouseAdapter{ //Override the mousePressed method public void mousePressed(MouseEvent e){ //Get x and y coordinates of the mouse pointer and // store in the instance variables of the MyCanvas // object. Note the requirement to cast the component // to the type of MyCanvas in order to access the // instance variables. ((MyCanvas)e.getComponent()).clickX = e.getX(); ((MyCanvas)e.getComponent()).clickY = e.getY(); //display coordinate information e.getComponent().repaint(); }//end mousePressed() }//end class MouseProc //=======================================================// //The following listener is used to terminate the program // when the user closes the frame. class WProc1 extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); }//end windowClosing() }//end class WProc1 //=======================================================// |
A - See the specifications and the
solution below.
/*File SampProg140.java Copyright 1997, R.G.Baldwin Illustrates the use of the Canvas class along with the requirement to establish the size of a Canvas object for use with certain types of layout managers. Also illustrates the ability to instantiate listener objects that can manipulate the source objects on which they are registered without the requirement to pass references to those source objects when the listener objects are instantiated. No parameterized constructors are used in the instantiation of listener objects in this program. When the program first appears on the screen, two green Canvas objects appear in a Frame object. The Frame object is approximately 300 by 300 pixels in size. One of the green Canvas objects is 100 pixels wide and 150 pixels in height. The other green Canvas object is 50 pixels wide and 150 pixels in height. The green Canvas objects are separated by a horizontal gap of 30 pixels when they are side-by-side and are separated by a vertical gap of 30 pixels when they are arranged in a column. When you click on either of the green Canvas objects, the coordinates of the mouse pointer are displayed near the mouse pointer. Clicking in the gaps between the Canvas objects, or clicking in the other area outside the Canvas objects has no effect on the program. Clicking on the close button on the Frame object terminates the program and returns control to the operating system. These results were produced using JDK 1.1.3, running under Windows 95. */ //=======================================================// import java.awt.*; import java.awt.event.*; //=======================================================// //Subclass Canvas in order to override the paint method // and to set the size and color of the Canvas object // when it is instantiated. class MyCanvas extends Canvas{ int clickX; int clickY; public MyCanvas(int width, int height){//constructor this.setBackground(Color.green); this.setSize(width,height); }//end constructor //Override the paint() method to display coordinate data public void paint(Graphics g){ g.drawString( "" + clickX + ", " + clickY, clickX, clickY); }//end paint() }//end class MyCanvas //=======================================================// class SampProg140 extends Frame{//controlling class public static void main(String[] args){ //instantiate an object of this type new SampProg140(); }//end main public SampProg140(){//constructor //Create a flow layout with gaps. FlowLayout myLayout = new FlowLayout(); myLayout.setVgap(30); myLayout.setHgap(30); this.setLayout(myLayout);//Apply layout to the Frame this.setTitle("Copyright 1997, R.G.Baldwin"); this.setSize(300,300); //Instantiate two green customized Canvas objects MyCanvas oneCanvasObject = new MyCanvas(100,150); MyCanvas anotherCanvasObject = new MyCanvas(50,100); //Add the MyCanvas objects to the Frame object. this.add(oneCanvasObject); this.add(anotherCanvasObject); this.setVisible(true);//make it all visible //Instantiate and register Listener object which will // terminate the program when the user closes the // Frame. WProc1 winProcCmd1 = new WProc1(); this.addWindowListener(winProcCmd1); //Instantiate and register Listener objects which will // process mouse events to determine and display the // coordinates when the user presses the mouse button // on either MyCanvas object. // Note that the Listener objects are instantiated // anonymously and no reference to the MyCanvas object // is passed to the constructors for the Listener // objects. oneCanvasObject.addMouseListener(new MouseProc()); anotherCanvasObject.addMouseListener(new MouseProc()); }//end constructor }//end class SampProg140 definition //=======================================================// //This listener class responds to mouse presses and // displays the coordinates of the mouse pointer when the // mouse is pressed on the object for which it is // registered. class MouseProc extends MouseAdapter{ //Override the mousePressed method public void mousePressed(MouseEvent e){ //Get x and y coordinates of the mouse pointer and // store in the instance variables of the MyCanvas // object. Note the requirement to cast the component // to the type of MyCanvas in order to access the // instance variables. ((MyCanvas)e.getComponent()).clickX = e.getX(); ((MyCanvas)e.getComponent()).clickY = e.getY(); //display coordinate information e.getComponent().repaint(); }//end mousePressed() }//end class MouseProc //=======================================================// //The following listener is used to terminate the program // when the user closes the frame. class WProc1 extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); }//end windowClosing() }//end class WProc1 //=======================================================// |