Before getting into the technical details, we will look at some relatively simple but interesting programs that illustrate the rendering of shapes and fonts. We will defer the rendering of images to a subsequent lesson. This lesson will explain the sample program in a general sense. Subsequent lessons will fill in the technical details of the Graphics class.
The program uses simple drawing techniques to create two fake buttons that appear (on some systems at least) to be green 3D button objects.
Note that these 3D buttons are not constructed using the Button class or the draw3DRect() method of the Graphics class. Rather, they are rendered using a simple drawRect() method of the Graphics class (which draws a 2D rectangle). The 3D effect results from a visual artifact of the drawing process.
When the program starts, two green fake buttons with captions of "Small" and "Large" are displayed in a Frame object along with a real Button that has a caption of "Button".
The green buttons initially appears to protrude slightly from the surface of the Frame object in a manner similar to the real Button object.
When you point to a green button and press the left mouse button, the green button appears to be depressed into the surface of the Frame object in a manner similar to a real Button object.
When you release the mouse button, the green button appears to pop back out and protrude from the surface of the Frame object.
Since this is an optical illusion, some observers may not experience the illusion in which case they will simply see green rectangles with text and lines on them.
The 3D effect is an artifact of the manner in which the rectangle is drawn onto an underlying Canvas object.
The fake buttons are instances of a class that subclasses the Canvas class. The program subclasses Canvas to override the paint() method in order to set the size and color of a Canvas object, to draw a rectangle which is partially on and partially off of the Canvas object, and to draw a caption on the Canvas object. The fact that the rectangle is only partially on the Canvas object causes the Canvas object to appear to protrude out of the screen, or to be depressed into the screen which produces the 3D effect.
The rectangle is offset either up and to the left relative to the Canvas object or down and to the right. In either case, two lines on the border of the rectangle are lost because they hang off the edge of the Canvas object. The remaining two lines appear to be shadows and this causes the 3D effect. When the two visible lines are on the right and bottom of the Canvas object, the button appears to protrude out of the screen. When the two visible lines are on the left and top of the Canvas object, the button appears to be depressed into the screen.
When you click on one of the green buttons, some text is displayed on the standard output device to confirm that the click occurred. Some text is also displayed when you click on the real Button object.
It may be significant to note that the fake green buttons are much more responsive than the real Button when running under Win95 on a machine with a 133MHz Pentium. This can be demonstrated by clicking repeatedly on one or the other as fast as you can click. The real Button appears to miss some of the clicks while the fake green buttons appear to respond properly to every click. At least the fake green buttons respond to a much higher percentage of clicks than the real Button.
These results were produced using JDK 1.1.3, running under Windows 95.
Two improved versions of this program are presented at the end of this lesson. The first improved version uses lines instead of rectangles to achieve the shadow effect. Double lines are used to enhance the shadow effect.
In addition, the caption on the button is caused to move slightly when the button is pushed. This also enhances the 3D effect by giving the illusion of motion to the button.
The second improved version draws highlights in addition to shadows on the button. In these two cases, a lighter or darker shade of the background color of the button (instead of black) is used to produce the effect. This produces a much more convincing illusion of a 3D button than the previous two versions of the program.
The instance variable named pushed is used in the overridden paint() method to determine how to render the fake button. This instance variable is initialized to false and later modified by a mouse listener object. When pushed is false, the fake button appears to protrude out of the screen, and when it is true, the fake button appears to be depressed into the screen.
The constructor simply accepts parameters for the width and height of the fake button along with a caption to display on the button and saves those parameters in a set of instance variables.
class FakeButtonClass extends Canvas{ boolean pushed = false;//indicates button pushed or not int width; //button width in pixels int height;//button height in pixels String caption;//caption for button public FakeButtonClass(//constructor int width,int height,String caption){ this.width = width; this.height = height; this.caption = caption; this.setBackground(Color.green); this.setSize(this.width,this.height); }//end constructor //... }//end class FakeButtonClass |
As you can see in the follow code fragment, the code for rendering the 3D button is very simple. A determination is made as to which edges of the rectangle should hang off the Canvas object using the value of the pushed instance variable. Then the drawRect() method is used to draw a rectangle on the Canvas object with the same dimensions as the Canvas object. The first two parameters of the drawRect() method specify the coordinates of the upper left-hand corner of the rectangle in its container (the Canvas object).
For the "depressed" case, the rectangle is offset down and to the right by one pixel causing the right and bottom border lines of the rectangle to be lost.
For the "protruding" case, the rectangle is offset up and to the left by one pixel causing the left and top border lines of the rectangle to be lost.
class FakeButtonClass extends Canvas{ //... public void paint(Graphics g){ if(pushed) g.drawRect(1,1,width,height); else g.drawRect(-1,-1,width,height); //... }//end paint() }//end class FakeButtonClass |
We will accomplish the positioning using an object of type FontMetrics. Such an object can be caused to contain information about the font being used in a particular Graphics object. We will have more to say about this in a subsequent lesson. For the time being, suffice it to say that we can obtain a FontMetrics object containing information about the font in our Graphics object by invoking the getFontMetrics() method on that object. Having the FontMetrics object, we can extract information about the font by invoking methods on the FontMetrics object.
Horizontal placement is easy. We determine the width in pixels of our caption by invoking the stringWidth() method on the FontMetrics object and passing the caption as a parameter. Then we do a little arithmetic to determine the horizontal coordinate where we should render the caption.
Vertical placement is a little more difficult. The getHeight() method returns a combination of several parameters that describe the font:
class FakeButtonClass extends Canvas{ //... String caption;//caption for button public void paint(Graphics g){ //... int fontHeight = g.getFontMetrics().getHeight(); int stringWidth = g.getFontMetrics().stringWidth(caption); g.drawString(caption, (width-stringWidth)/2,(height/2)+(fontHeight/4)); }//end paint() }//end class FakeButtonClass |
FakeButtonClass firstFakeButton = new FakeButtonClass(40,20,"Small"); FakeButtonClass secondFakeButton = new FakeButtonClass(80,40,"Large"); |
MouseListenerClass myMouseListener = new MouseListenerClass(); firstFakeButton.addMouseListener(myMouseListener); secondFakeButton.addMouseListener(myMouseListener); |
Note that the component object returned from getComponent() must be downcast before it can be used to access the pushed instance variable.
public void mousePressed(MouseEvent e){ ((FakeButtonClass)e.getComponent()).pushed = true; e.getComponent().repaint(); }//end mousePressed() |
This method also displays a message on the screen to confirm that the event has occurred.
public void mouseReleased(MouseEvent e){ //Display a message System.out.println("mouseReleased"); ((FakeButtonClass)e.getComponent()).pushed = false; e.getComponent().repaint(); }//end mouseReleased() |
/*File Shapes02.java.java Copyright 1997, R.G.Baldwin This program illustrates the use of the Canvas class and several of the methods of the Graphics class. The program creates two fake buttons that appear (on some systems at least) to be green 3D button objects. Note that the green 3D buttons are not constructed using the Button class or the draw3DRect() method of the Graphics class. When the program starts, two green fake buttons with captions of "Small" and "Large" along with a real Button with a caption of "Button" appear in a Frame object. The green buttons appears to protrude slightly from the surface of the Frame object in a manner similar to the real Button object. When you point to a green button with the mouse and press the left mouse button, the green button appears to become depressed into the surface of the Frame object in a manner similar to a real Button object. When you release the mouse button, the green button appears to pop back out of the surface of the Frame object. This is accomplished using a simple drawRect() method. The draw3DRect() method is not used in this case. The 3D effect is an artifact of the manner in which the rectangle is drawn onto an underlying Canvas object. The reason that the 3D effect appears is explained in the comments. When you click on a green button, some text is displayed on the standard output device to confirm that the click occurred. Some text is also displayed when you click on the real Button object. It may be significant to note that the fake green buttons are much more responsive than the real Button when running under Win95 on a machine with a 133MHz Pentium. This can be demonstrated by clicking repeatedly on one or the other as fast as you can click. The real Button appears to miss some of the clicks while the fake green buttons appear to respond properly to every click. At least the fake green buttons responds to a much higher percentage of clicks than the real Button. These results were produced using JDK 1.1.3, running under Windows 95. */ //=======================================================// import java.awt.*; import java.awt.event.*; //=======================================================// //This class is used to create a fake button object. //Subclass Canvas to override the paint method in order // to set the size and color of a Canvas object, to draw // a rectangle which is partially on and partially off // of the Canvas object, and to draw a caption on the // Canvas object. //The fact that the rectangle is only partially on the // Canvas object causes the Canvas object to appear to // protrude out of the screen, or to be depressed into the // screen which produces the 3D effect. //The rectangle is offset either up and to the left // relative to the Canvas object or down and to the right. // In either case, two lines on the border of the // rectangle are lost. The remaining two appear to be // shadows and this causes the 3D effect. class FakeButtonClass extends Canvas{ boolean pushed = false;//indicates button pushed or not int width; //button width in pixels int height;//button height in pixels String caption;//caption for button public FakeButtonClass(//constructor int width,int height,String caption){ this.width = width; this.height = height; this.caption = caption; this.setBackground(Color.green); this.setSize(this.width,this.height); }//end constructor public void paint(Graphics g){ //Determine offset and draw rectangle on Canvas object if(pushed) g.drawRect(1,1,width,height); else g.drawRect(-1,-1,width,height); //Draw the caption centered horizontally and slightly // above center vertically. For vertical placement, // use one-fourth the sum of leading, ascent, and // descent parameters of the font to calculate the // baseline position for the characters. int fontHeight = g.getFontMetrics().getHeight(); int stringWidth = g.getFontMetrics().stringWidth(caption); g.drawString(caption, (width-stringWidth)/2,(height/2)+(fontHeight/4)); }//end paint() }//end class FakeButtonClass //=======================================================// class Shapes02 extends Frame{//controlling class public static void main(String[] args){ //instantiate an object of this type new Shapes02(); }//end main public Shapes02(){//constructor this.setLayout(new FlowLayout()); this.setTitle("Copyright 1997, R.G.Baldwin"); this.setSize(300,150); //Instantiate two fake button objects of different // sizes and a real Button object FakeButtonClass firstFakeButton = new FakeButtonClass(40,20,"Small"); FakeButtonClass secondFakeButton = new FakeButtonClass(80,40,"Large"); Button myRealButton = new Button("Button"); //Add the buttons to the Frame object this.add(firstFakeButton); this.add(myRealButton); this.add(secondFakeButton); this.setVisible(true);//make it all visible //Instantiate a mouse listener object and register it // to listen for mouse events on the two fake buttons MouseListenerClass myMouseListener = new MouseListenerClass(); firstFakeButton.addMouseListener(myMouseListener); secondFakeButton.addMouseListener(myMouseListener); //Instantiate and register an action listener object // on the real Button object. myRealButton.addActionListener( new MyActionListenerClass()); //Instantiate and register a Listener object which will // terminate the program when the user closes the // Frame. WindowListenerClass myWindowListener = new WindowListenerClass(); this.addWindowListener(myWindowListener); }//end constructor }//end class Shapes02 definition //=======================================================// //This class is used to instantiate a listener object that // listens for mouse events on the fake buttons and causes // the visual rendering to switch between a protruding // image and a "pushed" image. Also a message is displayed // when the button is clicked. class MouseListenerClass extends MouseAdapter{ //Override the mousePressed() method public void mousePressed(MouseEvent e){ //Set the "pushed" variable to true and repaint ((FakeButtonClass)e.getComponent()).pushed = true; e.getComponent().repaint(); }//end mousePressed() //Override the mouseReleased() method public void mouseReleased(MouseEvent e){ //Display a message System.out.println("mouseReleased"); //Set the "pushed" variable to false and repaint ((FakeButtonClass)e.getComponent()).pushed = false; e.getComponent().repaint(); }//end mouseReleased() }//end class MouseListenerClass //=======================================================// //This class is used to instantiate a listener object that // listens for action events on the real button and // displays a message when it is clicked. class MyActionListenerClass implements ActionListener{ public void actionPerformed(ActionEvent e){ System.out.println("actionPerformed");//announce }//end actionPerformed() }//end class MyActionListenerClass //=======================================================// //The following listener is used to terminate the program // when the user closes the frame. class WindowListenerClass extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); }//end windowClosing() }//end class WindowListenerClass //=======================================================// |
A - See the following solution
/*File SampProg141.java.java Copyright 1997, R.G.Baldwin From lesson 160. Without viewing the solution that follows, write a Java application that replicates the functionality of the application named Shapes02.java but uses the drawLine() method in place of the drawRect() method. Use double width lines to emphasize the shadow effect. Also draw the caption with a slight shift when the button is pushed to give the visual impression of motion. This program illustrates the use of the Canvas class and several of the methods of the Graphics class. The program creates two fake buttons that appear (on some systems at least) to be green 3D button objects. When the program starts, two green fake buttons with captions of "Small" and "Large" along with a real Button with a caption of "Button" appear in a Frame object. The green buttons appears to protrude slightly from the surface of the Frame object in a manner similar to the real Button object. When you point to a green button with the mouse and press the left mouse button, the green button appears to become depressed into the surface of the Frame object in a manner similar to a real Button object. When you release the mouse button, the green button appears to pop back out of the surface of the Frame object. The 3D effect is an artifact of the manner in which the lines and the text are drawn onto an underlying Canvas object. The reason that the 3D effect appears is explained in the comments. It may be significant to note that the fake green buttons are much more responsive than the real Button when running under Win95 on a machine with a 133MHz Pentium. This can be demonstrated by clicking repeatedly on one or the other as fast as you can click. The real Button appears to miss some of the clicks while the fake green buttons appear to respond properly to every click. At least the fake green buttons responds to a much higher percentage of clicks than the real Button. These results were produced using JDK 1.1.3, running under Windows 95. */ //=======================================================// import java.awt.*; import java.awt.event.*; //=======================================================// //This class is used to create a fake button object. //Subclass Canvas to override the paint method in order // to set the size and color of a Canvas object, to draw // a series of lines on the Canvas object, and to draw a // caption on the Canvas object. //The lines are drawn so as to suggest shadows on the // right and bottom of the button when it is not pushed, // and to suggest shadows on the right and top of the // button when it is pushed. //The caption is drawn so as to move slightly down and to // the right when the button is pushed to give the illusion // of motion. //The combination of the shadow effect and the motion // effect produce the illusion of a 3D button being // pressed into the screen. class FakeButtonClass extends Canvas{ boolean pushed = false;//indicates button pushed or not int width; //button width in pixels int height;//button height in pixels String caption;//caption for button public FakeButtonClass(//constructor int width,int height,String caption){ this.width = width; this.height = height; this.caption = caption; this.setBackground(Color.green); this.setSize(this.width,this.height); }//end constructor public void paint(Graphics g){ //Draw the caption centered horizontally and slightly // above center vertically. For vertical placement, // use one-fourth the sum of leading, ascent, and // descent parameters of the font to calculate the // baseline position for the characters. int fontHeight = g.getFontMetrics().getHeight(); int stringWidth = g.getFontMetrics().stringWidth(caption); //Determine the state and draw corresponding lines on // Canvas object. //Also draw the caption and shift it slightly to give // the impression of motion when the button is pushed. if(pushed){ g.drawLine(0,0,width,0); g.drawLine(0,1,width,1); g.drawLine(0,0,0,height); g.drawLine(1,0,1,height); //Note the one-pixel x and y offset in the following // statement to give the impression that the button // has moved. g.drawString(caption, 1+(width-stringWidth)/2, 1+((height/2)+(fontHeight/4))); }//end if else{ //Note that a line drawn at height or width is off // the edge of the object and not visible. g.drawLine(0,height-1,width-1,height-1); g.drawLine(0,height-2,width-2,height-2); g.drawLine(width-1,0,width-1,height-1); g.drawLine(width-2,0,width-2,height-2); //Note that there is no motion offset in the // following statement. g.drawString(caption, (width-stringWidth)/2,(height/2)+(fontHeight/4)); }//end else }//end paint() }//end class FakeButtonClass //=======================================================// class SampProg141 extends Frame{//controlling class public static void main(String[] args){ //instantiate an object of this type new SampProg141(); }//end main public SampProg141(){//constructor this.setLayout(new FlowLayout()); this.setTitle("Copyright 1997, R.G.Baldwin"); this.setSize(300,150); //Instantiate two fake button objects of different // sizes and a real Button object FakeButtonClass firstFakeButton = new FakeButtonClass(40,20,"Small"); FakeButtonClass secondFakeButton = new FakeButtonClass(80,40,"Large"); Button myRealButton = new Button("Button"); //Add the buttons to the Frame object this.add(firstFakeButton); this.add(myRealButton); this.add(secondFakeButton); this.setVisible(true);//make it all visible //Instantiate a mouse listener object and register it // to listen for mouse events on the two fake buttons MouseListenerClass myMouseListener = new MouseListenerClass(); firstFakeButton.addMouseListener(myMouseListener); secondFakeButton.addMouseListener(myMouseListener); //Instantiate and register a Listener object which will // terminate the program when the user closes the // Frame. WindowListenerClass myWindowListener = new WindowListenerClass(); this.addWindowListener(myWindowListener); }//end constructor }//end class SampProg141 definition //=======================================================// //This class is used to instantiate a listener object that // listens for mouse events on the fake buttons and causes // the visual rendering to switch between a protruding // image and a "pushed" image. Also a message is displayed // when the button is clicked. class MouseListenerClass extends MouseAdapter{ //Override the mousePressed() method public void mousePressed(MouseEvent e){ //Set the "pushed" variable to true and repaint ((FakeButtonClass)e.getComponent()).pushed = true; e.getComponent().repaint(); }//end mousePressed() //Override the mouseReleased() method public void mouseReleased(MouseEvent e){ //Set the "pushed" variable to false and repaint ((FakeButtonClass)e.getComponent()).pushed = false; e.getComponent().repaint(); }//end mouseReleased() }//end class MouseListenerClass //=======================================================// //The following listener is used to terminate the program // when the user closes the frame. class WindowListenerClass extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); }//end windowClosing() }//end class WindowListenerClass //=======================================================// |
Make the background color of the fake button to be a parameter in the constructor for the class.
Cause the background color of your fake buttons to be the same color as the background color of their container. For example, an RGB color of 0,128,0 is an appropriate color for this purpose.
Cause the highlighted edge of your fake button to be a brighter shade of the background color of the button.
Cause the shadow edge of your fake button to be a darker shade of the background color of the button. This produces a much more convincing illusion of a 3D button than previous versions where only the shadow was drawn and it was drawn in black.
A - See solution below.
/*File SampProg142.java.java Copyright 1997, R.G.Baldwin From lesson 160. Without viewing the solution that follows, write a Java application that replicates the functionality of the application named SampProg141.java with the following differences Make the background color of the fake button to be a parameter in the constructor for the class. Cause the background color of your fake buttons to be the same color as the background color of their container. For example, an RGB color of 0,128,0 is an appropriate color for this purpose. Cause the highlighted edge of your fake button to be a brighter shade of the background color of the button. Cause the shadow edge of your fake button to be a darker shade of the background color of the button. This produces a much more convincing illusion of a 3D button than previous versions where only the shadow was drawn and it was drawn in black. The program creates two fake buttons that appear (on some systems at least) to be green 3D button objects. When the program starts, two green fake buttons with captions of "Small" and "Large" along with a real Button with a caption of "Button" appear in a Frame object. The green buttons appears to protrude slightly from the surface of the Frame object in a manner similar to the real Button object. When you point to a green button with the mouse and press the left mouse button, the green button appears to become depressed into the surface of the Frame object in a manner similar to a real Button object. When you release the mouse button, the green button appears to pop back out of the surface of the Frame object. As in previous versions of this application, the fake green buttons are much more responsive than the real Button when running under Win95 on a machine with a 133MHz Pentium. These results were produced using JDK 1.1.3, running under Windows 95. */ //=======================================================// import java.awt.*; import java.awt.event.*; //=======================================================// //This class is used to create a fake button object. //Subclass Canvas to override the paint method in order // to set the size and color of a Canvas object, to draw // a series of lines on the Canvas object, and to draw a // caption on the Canvas object. //The lines are drawn so as to suggest shadows and // highlights on the edges of a rectangular button object. //The caption is drawn so as to move slightly down and to // the right when the button is pushed to give the illusion // of motion. //The highlights and the shadows and the motion effect // combine to produce the illusion of a 3D button being // pressed into the screen and released to pop out. class FakeButtonClass extends Canvas{ boolean pushed = false;//indicates button pushed or not int width; //button width in pixels int height;//button height in pixels String caption;//caption for button public FakeButtonClass(//constructor int width,int height,String caption,Color color){ this.width = width; this.height = height; this.caption = caption; this.setBackground(color); this.setSize(this.width,this.height); }//end constructor public void paint(Graphics g){ int fontHeight = g.getFontMetrics().getHeight(); int stringWidth = g.getFontMetrics().stringWidth(caption); //Determine the state and draw corresponding lines on // the Canvas object. //Use lines which are darker and lighter than the // background color of the object. //Also draw the caption and shift it slightly to give // the impression of motion when the button is pushed. if(pushed){ //draw the shadow as dark green g.setColor(this.getBackground().darker()); g.drawLine(0,0,width,0); g.drawLine(0,1,width,1); g.drawLine(0,0,0,height); g.drawLine(1,0,1,height); //draw the highlight as light green g.setColor(this.getBackground().brighter()); g.drawLine(0,height-1,width-1,height-1); g.drawLine(0,height-2,width-2,height-2); g.drawLine(width-1,0,width-1,height-1); g.drawLine(width-2,0,width-2,height-2); //Draw the caption in black, centered horizontally // and slightly above center vertically. //Note the one-pixel x and y offset in the following // statement to give the impression that the button // has moved. g.setColor(Color.black); g.drawString(caption, 1+(width-stringWidth)/2, 1+((height/2)+(fontHeight/4))); }//end if else{ //Draw the shadow in dark green //Note that a line drawn at height or width is off // the edge of the object and not visible. g.setColor(this.getBackground().darker()); g.drawLine(0,height-1,width-1,height-1); g.drawLine(0,height-2,width-2,height-2); g.drawLine(width-1,0,width-1,height-1); g.drawLine(width-2,0,width-2,height-2); //Draw the highlight as light green g.setColor(this.getBackground().brighter()); g.drawLine(0,0,width,0); g.drawLine(0,1,width,1); g.drawLine(0,0,0,height); g.drawLine(1,0,1,height); //Draw the caption in black, centered horizontally // and slightly above center vertically. //Note that there is no motion offset in the // following statement. g.setColor(Color.black); g.drawString(caption, (width-stringWidth)/2,(height/2)+(fontHeight/4)); }//end else }//end paint() }//end class FakeButtonClass //=======================================================// class SampProg142 extends Frame{//controlling class public static void main(String[] args){ //instantiate an object of this type new SampProg142(); }//end main public SampProg142(){//constructor this.setLayout(new FlowLayout()); this.setTitle("Copyright 1997, R.G.Baldwin"); this.setSize(300,150); this.setBackground(new Color(0,128,0)); //Instantiate two fake button objects of different // sizes and a real Button object FakeButtonClass firstFakeButton = new FakeButtonClass( 40,20,"Small",this.getBackground()); FakeButtonClass secondFakeButton = new FakeButtonClass( 80,40,"Large",this.getBackground()); Button myRealButton = new Button("Button"); //Add the buttons to the Frame object this.add(firstFakeButton); this.add(myRealButton); this.add(secondFakeButton); this.setVisible(true);//make it all visible //Instantiate a mouse listener object and register it // to listen for mouse events on the two fake buttons MouseListenerClass myMouseListener = new MouseListenerClass(); firstFakeButton.addMouseListener(myMouseListener); secondFakeButton.addMouseListener(myMouseListener); //Instantiate and register a Listener object which will // terminate the program when the user closes the // Frame. WindowListenerClass myWindowListener = new WindowListenerClass(); this.addWindowListener(myWindowListener); }//end constructor }//end class SampProg142 definition //=======================================================// //This class is used to instantiate a listener object that // listens for mouse events on the fake buttons and causes // the visual rendering to switch between a protruding // image and a "pushed" image. Also a message is displayed // when the button is clicked. class MouseListenerClass extends MouseAdapter{ //Override the mousePressed() method public void mousePressed(MouseEvent e){ //Set the "pushed" variable to true and repaint ((FakeButtonClass)e.getComponent()).pushed = true; e.getComponent().repaint(); }//end mousePressed() //Override the mouseReleased() method public void mouseReleased(MouseEvent e){ //Set the "pushed" variable to false and repaint ((FakeButtonClass)e.getComponent()).pushed = false; e.getComponent().repaint(); }//end mouseReleased() }//end class MouseListenerClass //=======================================================// //The following listener is used to terminate the program // when the user closes the frame. class WindowListenerClass extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); }//end windowClosing() }//end class WindowListenerClass //=======================================================// |