The material in this lesson is extremely important. However, there is simply too much material to be covered in detail during lecture periods. Therefore, students in Prof. Baldwin's Advanced Java Programming classes at ACC will be responsible for studying this material on their own, and bringing any questions regarding the material to class for discussion.
This lesson was originally written on December 6, 1997 using the software and documentation in the JDK 1.1.3 download package.
This lesson will develop a new class for the lightweight button by converting two of the named inner classes to anonymous inner classes.
All of the class definition will remain the same except for the constructor and the removal of the two named inner classes. Therefore, all I am only going to show you is the constructor.
You can create your own version of this new class by using the new constructor, removing the named inner classes for the focus listener and the key listener from the class named LWButton02, and using the remainder of the class named LWButton02.
I'm not going to provide much discussion. You should already know how to convert the named inner classes to anonymous inner classes. If you don't, you should go back and review the lesson on inner classes.
A test program is provided at the end of the lesson that can be used to exercise this new version of the lightweight button class.
Please refer to the class named LWButton01 in a previous lesson for a complete functional description of the lightweight 3D button class.
Note that when you define an anonymous inner class, you are, in effect, implementing the listener interface. This requires that you provide a definition for all of the methods declared in the interface. Therefore, it was necessary for me to provide an empty function definition for the method named keytyped() even though I didn't need to use that method.
Also note that it wasn't possible to use an anonymous inner class for
the mouse listener. Use of an anonymous inner class implies that you are
instantiating an anonymous object. However, the functional requirements
of the program require that the methods of the key listener object invoke
methods of the mouse listener object. This requires that the mouse listener
object be a named object. You can see that in the following code which
references the mousePressed() and mouseReleased() methods
on the mouseListener object.
//Register an anonymous key listener object using an // anonymous inner class this.addKeyListener( new KeyListener(){ public void keyPressed(KeyEvent e){ //Generate mousePressed() event if(e.getKeyCode() == KeyEvent.VK_SPACE) mouseListener.mousePressed(new MouseEvent( refToThis,MouseEvent.MOUSE_PRESSED, 0,0,0,0,0,false)); }//end keyPressed() public void keyReleased(KeyEvent e){ //Generate mouseReleased() event if(e.getKeyCode() == KeyEvent.VK_SPACE) mouseListener.mouseReleased(new MouseEvent( refToThis,MouseEvent.MOUSE_RELEASED, 0,0,0,0,0,false)); }//end keyReleased() public void keyTyped(KeyEvent e){}//satisfy compiler }//end KeyListener );//end addKeyListener //end of anonymous inner class for key listener |
//Register an anonymous focus listener object using an // anonymous inner class. this.addFocusListener( new FocusListener(){ public void focusGained(FocusEvent e){ gotFocus = true; //set the gotFocus flag refToThis.invalidate(); refToThis.repaint(); }//end focusGained() public void focusLost(FocusEvent e){ gotFocus = false; //clear the gotFocus flag refToThis.invalidate(); refToThis.repaint(); }//end focusLost() }//end FocusListener );//end addFocusListener //end of anonymous inner class for focus listener |
It was pointed out by a reader named Kees Kuip that the use of the refToThis instance variable could lead to a memory leak, because the object has an embedded reference to itself which could prevent it from being garbage-collected. A solution to this potential problem was provided as an exercise for the student in the Review section at the end of an earlier lesson. As it turns out, this is not a problem. A demonstration program to that effect was also provided in the earlier lesson. Thanks go out to Kees for pointing out this potential problem, and also for recommending a solution.
/* File LWButton03.java Copyright 1997, R.G.Baldwin This class replicates the functionality of the class named LWButton01 and is a modification of the class named LWButton02. However, the LWButton01 class was implemented using the enableEvents()--process...Event() methodology whereas this class uses the source/listener methodology. Two of the listener classes in this class are anonymous inner classes while one of the listener classes is a named inner class. This class was tested using JDK 1.1.3 under Win95. */ //=======================================================// //Constructor for an LWButton with a label. public LWButton03(String rawLabel) { this.rawLabel = rawLabel; //Add spaces on either end and save it that way this.label = " " + rawLabel + " "; //Instantiate and register a named listener object for // the mouse listener. mouseListener = new MyMouseListenerClass(); this.addMouseListener(mouseListener); //Register an anonymous key listener object using an // anonymous inner class this.addKeyListener( new KeyListener(){ public void keyPressed(KeyEvent e){ //Generate mousePressed() event if(e.getKeyCode() == KeyEvent.VK_SPACE) mouseListener.mousePressed(new MouseEvent( refToThis,MouseEvent.MOUSE_PRESSED, 0,0,0,0,0,false)); }//end keyPressed() public void keyReleased(KeyEvent e){ //Generate mouseReleased() event if(e.getKeyCode() == KeyEvent.VK_SPACE) mouseListener.mouseReleased(new MouseEvent( refToThis,MouseEvent.MOUSE_RELEASED, 0,0,0,0,0,false)); }//end keyReleased() public void keyTyped(KeyEvent e){}//satisfy compiler }//end KeyListener );//end addKeyListener //end of anonymous inner class for key listener //Register an anonymous focus listener object using an // anonymous inner class. this.addFocusListener( new FocusListener(){ public void focusGained(FocusEvent e){ gotFocus = true; //set the gotFocus flag refToThis.invalidate(); refToThis.repaint(); }//end focusGained() public void focusLost(FocusEvent e){ gotFocus = false; //clear the gotFocus flag refToThis.invalidate(); refToThis.repaint(); }//end focusLost() }//end FocusListener );//end addFocusListener //end of anonymous inner class for focus listener //Store a reference to this lightweight button object // in an instance variable refToThis = this; }//end constructor |
Please refer to the earlier lesson for a functional description of the
program.
/* File Lightweight08.java Copyright 1997, R.G.Baldwin This program was tested using JDK 1.1.3 under Win95. */ //=======================================================// import java.awt.*; import java.awt.event.*; //=======================================================// public class Lightweight08 extends Frame{ Label myLabel; public static void main(String[] args){ new Lightweight08();//instantiate object of this type }//end main //-------------------------------------------------------// public Lightweight08(){//constructor this.setTitle("Copyright 1997, R.G.Baldwin"); //Set background to a dull yellow this.setBackground(new Color(128,128,0)); //Create a borderLayout object with gaps and apply // it to the Frame object. BorderLayout myLayout = new BorderLayout(); myLayout.setHgap(10); myLayout.setVgap(10); this.setLayout(myLayout); //Instantiate three lightweight buttons LWButton03 eastLWButton = new LWButton03("East"); LWButton03 northLWButton = new LWButton03("North"); LWButton03 centerLWButton = new LWButton03("Center"); //Instantiate a Label object and initialize it to green myLabel = new Label("Label Object"); myLabel.setBackground(Color.green); //Instantiate a heavyweight button object Button myButton = new Button("Heavyweight Button"); //Add all five components to the Frame object. this.add(eastLWButton,"East"); this.add(northLWButton,"North"); this.add(centerLWButton,"Center"); this.add(myButton,"West"); this.add(myLabel,"South"); //Instantiate an ActionListener object MyActionListener myActionListener = new MyActionListener(); //Register the ActionListener object on all four // of the buttons. eastLWButton.addActionListener(myActionListener); northLWButton.addActionListener(myActionListener); centerLWButton.addActionListener(myActionListener); myButton.addActionListener(myActionListener); this.setSize(300,200); this.setVisible(true); //Anonymous inner-class listener to terminate program this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0);}});//end addWindowListener }//end constructor //-----------------------------------------------------// //Inner Class to respond to action events. Make this an // inner class for easy access to myLabel. class MyActionListener implements ActionListener{ public void actionPerformed(ActionEvent e){ if(myLabel.getBackground() == Color.green) myLabel.setBackground(Color.red); else myLabel.setBackground(Color.green); }//end actionPerformed }//end class MyActionListener }//end class Lightweight08 //=======================================================// |