640 likes | 776 Views
Object-Oriented Programming (Java), Unit 19. Kirk Scott. Panels, Adapter Classes, Anonymous Inner Classes, and Application Classes. 19.1 Panels and Adapter Classes 19.2 Anonymous Inner Classes 19.3 Application Classes. 19.1 Panels.
E N D
Object-Oriented Programming (Java), Unit 19 Kirk Scott
Panels, Adapter Classes, Anonymous Inner Classes, and Application Classes • 19.1 Panels and Adapter Classes • 19.2 Anonymous Inner Classes • 19.3 Application Classes
19.1 Panels • It turns out that the overall structure for applications is boxes within boxes. • This is the simple way of describing a containment hierarchy. • This provides a convenient way of organizing program components. • Not incidentally, putting things into panels has beneficial effects.
Echo7 • The screen shot for Echo7 is shown on the following overhead. • The visible difference between Echo6 and Echo7 is that the text field is given a fixed width. • It turns out that in order for this to take effect, the text field has to be put into a panel.
Structural and syntactical changes in Echo7: • The text field is given default text. • The text field is given a size. • The units for the width of the field do not correspond to the number of characters of the default font that are displayed in the field. • The text field is put into its own panel in the frame. • If the text field is not put into its own panel, giving it a size has no effect.
Structural and syntactical changes in Echo7, cont’d.: • In Echo7 the application frame has an instance of the WindowCloser class. • The window closer is a kind of listener. • This listener defines what is to be done when the application is closed.
The Adapter classes • Recall that the text field listener, for example, was created by implementing the ActionListener interface. • A listener in general may be created by implementing an interface. • Note however, that the WindowCloser class is a subclass of the WindowAdapter class, not an implementer of the WindowListener interface. • What does this mean?
An interface contains a signature for a method. • public void someMethod(parameter); • The corresponding adapter class contains an empty implementation. • public void someMethod(parameter) • { • }
The Adapter classes, cont’d.: • Java provides an adapter class that corresponds to a listener class. • If you extend the adapter class, you inherit the empty implementations of all of the other methods. • You only need to override the methods that your class will need. • This is a minor convenience provided in the Java API.
Unlike with an interface, you do not have to include implementations of unneeded methods. • In this example only the windowClosing() method is overridden. • If a listener interface like ActionListener only has one method, there is no need to use an adapter.
The UML diagram: • The UML diagram for Echo7 reflects all of the changes mentioned above. • The listeners, the window closer, and the text field listener continue to be inner classes of the application frame.
The UML sequence diagram: • Java’s event handling mechanism is reminiscent of looping. • The sequence diagram on the next overhead shows that part of the application which is conceptually the body of the loop. • It outlines the full sequence of calls triggered by a call to actionPerformed(), the method in the text field listener.
The code for Echo7: • import java.awt.*; • import java.awt.event.*; • import javax.swing.*; • public class Echo7 • { • public static void main(String[] args) • { • Echo7Frame myframe = new Echo7Frame(); • myframe.setVisible(true); • } • }
class Echo7Frame extends JFrame • { • private JTextField myField; • private Echo7Panel myOutputPanel; • private JPanel myInputPanel; • private final int FRAMEW = 500; • private final int FRAMEH = 500;
public Echo7Frame() • { • setTitle("Echo7 Frame"); • setSize(FRAMEW, FRAMEH); • myOutputPanel = new Echo7Panel(); • myField = new JTextField("xyz", 24); • TextFieldListener myListener = new TextFieldListener(); • myField.addActionListener(myListener); • myInputPanel = new JPanel(); • myInputPanel.add(myField); • Container contentPane = getContentPane(); • contentPane.add(myOutputPanel, "Center"); • contentPane.add(myInputPanel, "North"); • addWindowListener(new WindowCloser()); • }
private class TextFieldListener implements ActionListener • { • public void actionPerformed(ActionEvent event) • { • String inputString = myField.getText(); • myOutputPanel.setString(inputString); • myField.setText(""); • myOutputPanel.repaint(); • } • }
private class WindowCloser extends WindowAdapter • { • public void windowClosing(WindowEvent event) • { • System.exit(0); • } • } • }
class Echo7Panel extends JPanel • { • private String stringInQuestion = ""; • private final int STRINGX = 140; • private final int STRINGY = 240; • public Echo7Panel() • { • } • public void paintComponent(Graphics g) • { • Graphics2D g2 = (Graphics2D) g; • super.paintComponent(g2); • g2.drawString(stringInQuestion, STRINGX, STRINGY); • } • public void setString(String stringIn) • { • stringInQuestion = stringIn; • } • }
Echo8 • Anonymous inner classes can be used when a single instance of a class is needed and there is no reason for the class to have a name. • Anonymous classes are cryptic. • This syntax will not be used in further example programs.
It is worth hearing about anonymous inner classes because you may encounter code where they have been used. • No screenshot is given for this example because the code still functions like the previous example.
There is no official UML notation for anonymous inner classes: • The inability to include anonymous inner classes as labeled elements in a diagram is a (slight) drawback. • A small UML diagram is shown below which suggests that the Echo8Frame class has an anonymous inner class which implements the ActionListener interface.
The code for Echo8: • The code below shows the syntax for making an instance of ActionListener an anonymous inner class. • The listener is constructed inside the constructor for the frame class. • As an anonymous inner class, the definition of the ActionListener actually occurs in place, where it is constructed. • Therefore, the ActionListener class is an inner class of the frame class.
When constructing the instance of ActionListener, the keyword new is followed by a call to a default constructor. • The default constructor call is followed immediately by an opening brace, followed by the class definition, followed by a closing brace. • Because the class is anonymous, at no point in this syntax is a name given to the class.
The class definition consists entirely of the implementation of the actionPerformed() method, which is required in an ActionListener implementation. • The closing brace which follows the definition of actionPerformed() and signals the end of the class definition is followed immediately by a semicolon.
This semicolon is the end of the statement that began as construction. • Not only is an anonymous class like this an inner class of another class—its entire definition occurs in a single line of code which constructs an instance of the class. • Code illustrating this follows.
import java.awt.*; • import java.awt.event.*; • import javax.swing.*; • public class Echo8 • { • public static void main(String[] args) • { • Echo8Frame myframe = new Echo8Frame(); • myframe.setVisible(true); • } • }
class Echo8Frame extends JFrame • { • private JTextField myField; • private Echo8Panel myOutputPanel; • private JPanel myInputPanel; • private final int FRAMEW = 500; • private final int FRAMEH = 500;
public Echo8Frame() • { • setTitle("Echo8 Frame"); • setSize(FRAMEW, FRAMEH); • myOutputPanel = new Echo8Panel(); • myField = new JTextField("xyz", 24);
/* A call is made to construct an instance of a class that implements the interface. The definition of the class immediately follows the constructor, and is part of the same line of code. */ • ActionListener myListener = new ActionListener() • { • public void actionPerformed(ActionEvent event) • { • String inputString = myField.getText(); • myOutputPanel.setString(inputString); • myField.setText(“”); • myOutputPanel.repaint(); • } • };
myField.addActionListener(myListener); • JPanel myInputPanel = new JPanel(); • myInputPanel.add(myField); • Container contentPane = getContentPane(); • contentPane.add(myOutputPanel, "Center"); • contentPane.add(myInputPanel, "North"); • addWindowListener(new WindowCloser()); • }
private class WindowCloser extends WindowAdapter • { • public void windowClosing(WindowEvent event) • { • System.exit(0); • } • } • }
class Echo8Panel extends JPanel • { • private String stringInQuestion = ""; • private final int STRINGX = 140; • private final int STRINGY = 240; • public Echo8Panel() • { • } • public void paintComponent(Graphics g) • { • Graphics2D g2 = (Graphics2D) g; • super.paintComponent(g2); • g2.drawString(stringInQuestion, STRINGX, STRINGY); • } • public void setString(String stringIn) • { • stringInQuestion = stringIn; • } • }
Echo9 • Echo9 introduces a cup class. • A cup contains a seed count and it also has attributes that describe it as a rectangle with x and y coordinates in the frame. • The application accepts an integer value in the text field which is used to set the seedCount of the cup. • When the seedCount is set, the application has to be repainted in order to reflect the change.
The Echo9 screenshot: • In the screenshot a cup is represented by a rectangle. • The value of the seedCount variable is given using Unicode.
The UML Static Structure Diagram: • The UML structure diagram differs from the previous one only by the presence of the Cup class instead of a String in the output panel.
More on the UML Static Structure Diagram: • You can identify an input side and an output side of the application. • Actions which take in a value and change the state of the application are input. • Actions that are triggered by the call to repaint() and follow it, which cause the state of the application to be shown, are output.
The text field listener has access to the instance of the Echo9Panel, the output panel, which is an instance variable of the frame. • When a seed count is entered into the text field, the listener calls the setCup() method on the panel, passing in the count. • The setCup() method calls the setSeedCount() method on the cup belonging to the panel, passing in the count. • The listener then calls repaint() on the panel.
UML Sequence Diagrams for the Application • The first sequence diagram shows the actions that occur on the input side of the application:
The second sequence diagram shows the actions that occur on the output side of the application: • In other words, this is the sequence of method calls triggered by the call to repaint().
The call to repaint() triggers a call to the paintComponent() method of Echo9Panel. • Inside paintComponent() a call is made to drawCup(). • The graphics parameter is passed from paintComponent() to drawCup(), where methods to draw the rectangle and display the seedCount of the cup are called on the graphics parameter.
This technique of passing the graphics parameter around may not be entirely intuitive. • It raises the question of what the graphics object might be considered to be. • I think of it as the “pen” for an application, that thing that painting is done with.
I also think of there being only one pen per application. • It arises in the paintComponent() method for a panel class. • Because there is only one, it is passed around so that it can be used in different locations where the logic for painting is defined. • For example, the logic for painting or displaying a cup is defined in the Cup class.