Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Further Object-Oriented Programming Lecture 5 Graphical User Interface Review Implementing event-handlers using Inner Classes Elena Lazovska Faculty of Computer Science and IT New York University Skopje [email protected] 1 The Abstract Windowing Toolkit AWT The Abstract Windowing Toolkit provides a set of GUI components in the package java.awt The AWT supports the most common user interface idioms The AWT makes use of the GUI components of the underlying platform • Has the look and feel of the native windowing toolkit • The same AWT GUI may have a different appearance on different platforms With J2SE came Swing components that allow a uniform look and feel to be specified across different platforms • Most Swing components are pure Java components 2 The Java Foundation Classes JFC The Java Foundation Classes form a set of classes for cross platform GUI development The Swing GUI components are part of JFC • They exist in the package javax.swing • Swing makes use of some of the classes found in AWT Swing provides alternatives to most of the GUI components found in AWT • For examples JButton is a Swing alternative to Button found in AWT • Swing GUI components are more portable and flexible than the original AWT GUI components and generally preferred 3 Java GUI programming utilizes the classes shown in this hierarchical diagram 4 JComponent and its subclasses are the basic elements for building graphical user interfaces 5 Composite Design Pattern GUI components need to be displayed somewhere • A container manages a set of components Java makes use of the Composite Design Pattern • A component is the super class • A container IS A component but HAS A collection of components 6 JFrame – A Swing Container JFrame is an example of a top level swing container • As are JDialog, JWindow and JApplet A top level swing container contains an instance of JRootPane JRootPane extends JComponent and contains: • A Component called the Glass Pane • A JLayeredPane A JlayeredPane contains: • A Container called the ContentPane that is accessible via the getContentPane method of the top level swing container • An optional JMenuBar 7 Using JFrame JFrame theFrame = new JFrame("Testing JFrame"); theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); theFrame.setSize(300,100); theFrame.setVisible(true); 8 Extending the JFrame class Normally JFrame is used as a starting point: import java.awt.*; import javax.swing.*; public class PeteFrame extends JFrame { private JButton button1; private JLabel label1; public PeteFrame (String sTitle) { super (sTitle); Container contentPane; contentPane = getContentPane(); contentPane.setLayout(new FlowLayout()); 9 Extending the JFrame class (continued) button1 = new JButton("A button"); label1 = new JLabel("this is a label"); contentPane.add(label1); contentPane.add(button1); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(300,100); this.setVisible(true); } public static void main(String args[]) { new PeteFrame("Pete's sample frame"); } } 10 Content Pane Delegation As from JDK 1.5 just use the JFrame’s add method • Known as content Pane Delegation import java.awt.*; import javax.swing.*; public class PeteFrame extends JFrame { private JButton button1; private JLabel label1; public PeteFrame(String sTitle) { super(sTitle); button1 = new JButton("A button"); label1 = new JLabel("this is a label"); setLayout(new FlowLayout()); add(label1); add(button1); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(300, 100); this.setVisible(true); } public static void main(String args[]) { new PeteFrame("Pete's sample frame"); } } 11 Closing JFrames It is possible to choose what happens when a JFrame is closed The setDefaultCloseOperation is used It takes a single argument and suitable constants are defined in JFrame: • DO_NOTHING_ON_CLOSE • HIDE_ON_CLOSE • DISPOSE_ON_CLOSE • EXIT_ON_CLOSE For example from the previous slide: • this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 12 Layout Manager How are the components positioned within a container? How do you want them to be positioned? Java allows the positioning to be decoupled from the container • The container HAS A Layout Manager • A suitable layout can be plugged in 13 Layout Manager The positions of the components added to a container is determined by a layout manager In the previous example a flow layout manager was used • contentPane.setLayout(new FlowLayout()); Some examples of existing layout managers are: • FlowLayout – left to right and horizontally centred • BorderLayout – NORTH, SOUTH, EAST, WEST and CENTER • GridLayout - evenly spaced rows and columns • GridBagLayout • CardLayout 14 Events We know how to add GUI components but at the moment there is little or no user interaction Java GUIs are event driven • Any user interaction with a GUI component generates an event • An application handles the events An application must explicitly listen for events The component on which an event is fired or generated is called the source object or source component. For example a JButton generates an event when it is clicked A JButton can have an ActionListener added The ActionListener has a method called actionPerformed that is invoked when the button is clicked 15 JButton and the ActionListener Interface Java makes use of the following design pattern to allow application specific code to be added to handle an event 16 Adding an ActionListener import java.awt.*; import java.awt.event.*; import javax.swing.*; public class MyFrame extends JFrame{ private JButton stopButton; … public MyFrame (String sTitle) { … stopButton = new JButton("Stop"); stopButton.addActionListener( new StopButtonListener()); add(stopButton); … 17 Building the ActionListener The ActionListener interface specifies one method that must be implemented to realize the interface class StopButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.exit(0); } } Note the ActionEvent that is passed to the method • This describes the event in more detail In this example the application exits when the button is clicked 18 Using this class as the ActionListener in the previous example we defined the ActionListener for the JButton in a separate class it is also possible for the class that holds the reference to the JButton object to listen for the JButton events • the class will need to implement the ActionListener interface • and contain an actionPerformed() method public class MyFrame extends JFrame implements ActionListener{ private JButton stopButton; public MyFrame (String sTitle) { stopButton = new JButton("Stop"); stopButton.addActionListener(this); contentPane.add(stopButton); ...} public void actionPerformed(ActionEvent e) { System.exit(0); } }.... 19 Events if the same event handler is used for more than one component we need a way to distinguish them The ActionEvent e passed into the actionPerformed method contains information about the event One piece of information is the component that generated the event • This is obtained using the getSource method • e.getSource( ) if (e.getSource() == stopButton) System.exit(0); else if (e.getSource() == messageButton) { JOptionPane.showMessageDialog(this, label1.getText()); } 20 Writing a separate event handler class vs. Implementing the ActionListener interface in the containing class and using it as the event handler what are the advantages and disadvantages these two approaches? 21 A better way? we need an approach that allows us to • separate the container-class code from the event-handling code • yet allow the container and the event-handler to access each other’s member variables • and preferably have a separate class to handle each event – rather than having a long selection statement to decide on the appropriate action for a given event • want to increase cohesion without unnecessary coupling the solution is to use an inner class • An inner class has access to the enclosing class 22 Using Inner Classes public class MyFrame extends JFrame { private JButton stopButton; private JButton messageButton; private JLabel label1; public MyFrame (String sTitle) { ..... stopButton.addActionListener(new StopButtonListener()); messageButton.addActionListener(new MessageButtonListener()); ....... } private class StopButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.exit(0); } } private class MessageButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(MyFrame.this, label1.getText()); } 23 } Using Inner Classes note that JOptionPane.showMessageDialog takes a reference to the parent frame which is this instance of the outer class • not the inner class • referenced using MyFrame.this OuterClassName.this is a reference to the outer class instance 24 Anonymous Inner Classes in the last example, only one instance of each inner class was created • when providing a parameter to the addActionListener method of the appropriate JButton why not define the class where it is used? • if we do this, we don’t even need to name it ActionListener sbl = new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }; stopButton.addActionListener(sbl); 25 Anonymous Inner classes ActionListener sbl = new ActionListener() { ..... we declare sbl to be of type ActionListener • that means it must be an instance of a class that implements the ActionListener interface ActionListener sbl = new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }; we then construct an instance of our anonymous class that implements this interface, using the keyword new the definition of the class follows the call to the constructor, within brackets { } the class implements the actionPerformed method defined by the interface the entire statement ends with a semicolon • after the closing } of the anonymous class 26 Anonymous Inner classes an anonymous inner class can either • implement an interface • or extend a class the syntax is the same in both cases if it extends a class, it cannot define any new methods • remember the reference is to an instance of the superclass • so there is no way to call any new subclass methods • the anonymous class can override existing superclass methods, and implement abstract ones 27 Anonymous Inner classes /** from SCJP*/ run: public class AnnonymousDriver { popcorn public static void main(String args[]){ annonymous popcorn Popcorn popcorn = new Popcorn(); popcorn.pop(); Food f =new Food(); Popcorn p=f.getP(); p.pop(); } } class Popcorn { public void pop() { System.out.println("popcorn"); } } class Food { private Popcorn p = new Popcorn() { public void pop() { System.out.println("annonymous popcorn"); } }; public Popcorn getP() { return p; } } 28 Argument-defined Anonymous Inner Classes in the preceding example the object sbl created using the anonymous class definition was only used as an argument to the JButton’s addActionListener method there was actually no need to define the class and create the instance in advance instead, the entire class can be anonymously specified and created in the method argument list stopButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } } ); make sure the brackets match! 29 Argument-define Anonymous Inner Classes this syntax may look strange, but it is commonly used to define GUI event handlers the event handler code is defined at the same place it is attached to its component no unnecessary object references are created if the event-handling code is more than a few lines, can put it in a separate outer class method and call the method from the inner class 30 Summary In this lecture we have: • briefly review GUI programming in Java • looked at different ways of defining event handling classes for active components • seen that inner classes, and particularly anonymous inner classes, are useful in defining event handlers Reading GUIs • Liang chapters 15 and 11 • Sun Java tutorial "Creating a GUI with JFC / Swing" Inner classes • Liang sections 15.2 and 15.3 • Sun Java tutorial “Learning the Java Language: Classes and Objects: Nested classes” 31