|
||
10. Event HandlingTo understand the Java event modelTo accept mouse and text input in applets and applicationsTo display frame windowsTo understand how user interface components are added to a frame windowEvents, Event Listeners, and Event SourcesWhenever the user of a graphical program uses the mouse or types characters, the Java window manager sends a notification to the program that an event has occurred.When the mouse moves a tiny interval over a window, a “mouse move” event is generated.Every program must indicate which events it likes to receive by installing event listener objects.To install a listener, you need to know the event source.The event source is the user interface component that generates a particular event.For example, a button is the event source for button click events.A menu item is the event source for a menu selection event.We have to tell the event source which event listeners we want to install.Let’s listen to mouse clicks in an applet.There are three classes involved:The event class. In the mouse click, this is the class MouseEvent. The mouse event object can tell you the x- and y- positions of the mouse pointer and which mouse button the user clicked.The listener class. In the mouse click, this must be a class that implements the MouseListener interface. The mouse listener has several methods, each method has a MouseEvent parameter.The event source. This is the component that generates the mouse event and that manages the listeners. The event source is the applet whose area on the screen the user may click with the mouse.All event classes are subclasses of the EventObject class.The EventObject class has an important method, getSource, that returns the object that generated this event.Inheritance Diagram
MouseEvent ClassEach subclass also has its own methods that describes the event further.The MouseEvent class has methods:getX and getY that tell the position of the mouse at the time the event was generated.To activate the mouse handling, a mouse listener must implement the MouseListener interface and the following five methods:public interface MouseListener{ void mouseClicked(MouseEvent event);// called when the mouse has been clickedvoid mouseEntered(MouseEvent event);// called when the mouse enters a componentvoid mouseExited(MouseEvent event);// called when the mouse exits a componentvoid mousePressed(MouseEvent event);// called when a mouse button has been pressedvoid mouseReleased(MouseEvent event);// called when a mouse button has been released}Example: MouseSpyApplet.java// MouseSpy class (event class) for MouseSpyApplet.javapublic class MouseSpy implements MouseListener{ public void mouseClicked(MouseEvent event){ System.out.println(“Mouse clicked. x = “ +event.getX() + ”y = “ + event.getY());}public void mouseEntered(MouseEvent event){ System.out.println(“Mouse entered. x = “ +event.getX() + “y = “ + event.getY());}public void mouseExited(MouseEvent event){ System.out.println(“Mouse exited. x = “ +event.getX() + “y = “ + event.getY());}public void mousePressed(MouseEvent event){ System.out.println(“Mouse pressed. x = “ +event.getX() + “y = “ + event.getY());}public void mouseReleased(MouseEvent event){ System.out.println(“Mouse released. x = “ +event.getX() + “y = “ + event.getY());}}The listener methods simply print out the cause of the event and the x- and y- coordinate of the mouse.Next, we need to install the listener and call addMouseListener method of the event source which is the applet that receives the mouse clicks.// MouseSpyApplet.javapublic class MouseSpyApplet extends Applet{ public MouseSpyApplet(){ MouseSpy listener = new MouseSpy();addMouseListener(listener);}}When the user clicks the mouse in the applet, what method are called?listener.mousePressed(event1) and listener.mouseReleased(event2)If the press and release were in quick succession, the applet also calls listener.clicked(event3).
Event AdaptersUsually, a program is not interested in all listener notifications.For example, a program may only be interested in mouse clicks and may not care that these mouse clicks are composed of “mouse pressed” and “mouse released” events.The program could supply a listener that defines those non-interested methods as “do nothing” methods.public class MouseClickListener implements MouseListener{ public void mouseClicked(MouseEvent event){ // mouse click action here}public void mouseEntered(MouseEvent event){ // do nothing}public void mouseExited(MouseEvent event){ // do nothing}public void mousePressed(MouseEvent event){ // do nothing}public void mouseReleased(MouseEvent event){ // do nothing}}Java has provided an adapter class that implements the MouseListener interface such that all methods do nothing.public class MouseAdapter implements MouseListener{ // this class is defined in java.awt.event packagepublic void mouseClicked(MouseEvent event){ // do nothing}public void mouseEntered(MouseEvent event){ // do nothing}public void mouseExited(MouseEvent event){ // do nothing}public void mousePressed(MouseEvent event){ // do nothing}public void mouseReleased(MouseEvent event){ // do nothing}}Then we can define a listener by extending the MouseAdapter class and overriding just the methods that we care about.public class MouseClickListener extends MouseAdapter{ public void mouseClicked(MouseEvent event){ // mouse click action here}}The java.awt.event package contains an adapter class for all event listener interfaces that have at least two methods.For example, the WindowListener, a class with seven methods, has WindowAdapter class that defines all seven methods to do nothing.Inner ClassesSuppose we want to write a program that moves an ellipse to the mouse click position.Here is a program that draws an ellipse on the screen.The ellipse is stored as an instance variable for later use.import java.applet.Applet;import java.awt.Graphics;import java.awt.Grahpics2D;import java.awt.geom.Ellipse2D;public class EggApplet extends Applet{ private Ellipse2D.Double egg;private static final double EGG_WIDTH = 15;private static final double EGG_HEIGHT = 25;public EggApplet(){ egg = new Ellipse2D.Double(0, 0, EGG_WIDTH, EGG_HEIGHT);}public void paint(Graphics g){ Graphics2D g2 = (Graphics2D) g;g2.draw(egg);}}Now, let’s add a mouse listener that listens to a mouse click and moves the ellipse.public class EggApplet extends Applet{ public EggApplet(){ egg = new Ellipse2D.Double(0, 0, EGG_WIDTH, EGG_HEIGHT);// add mouse click listenerMouseClickListener listener = newMouseClickListener();addMouseListener(listerner);}. . .}class MouseClickListener extends MouseAdapter{ public void mouseClicked(MouseEvent event){ int mouseX = event.getX();int mouseY = event.getY();// now move the ellipse to (mouseX, mouseY)}}Unfortunately, the MouseClickListener class has no access to the private egg instance variable.To solve this problem, we can make the listener into an inner class.An inner class is defined inside another class.The inner class acts like a regular class, i.e., we can construct objects and invoke methods as usual.However, the methods of the inner class are allowed to access the private instance variables of the outer class.We can turn the MouseClickListener into an inner class as follow:public class EggApplet extends Applet{ private Ellipse2D.Double egg;public EggApplet(){ egg = new Ellipse2D.Double(0, 0, EGG_WIDTH, EGG_HEIGHT);// add mouse click listenerMouseClickListener listener = newMouseClickListener();addMouseListener(listerner);}…private Ellipse2D.Double egg;// inner class definitionclass MouseClickListener extends MouseAdapter{ public void mouseClicked(MouseEvent event){ int mouseX = event.getX();int mouseY = event.getY();// move the ellipse to (mouseX, mouseY)egg.setFrame(mouseX - EGG_WIDTH / 2,mouseY – EGG_HEIGHT / 2,EGG_WIDTH, EGG_HEIGHT);repaint();}}}The mouseClicked method of the inner class can now access the egg instance variable.Whenever we refer to an instance variable of an outer class inside an inner-class method, then the following process occurs:1. The inner-class object retrieves the reference to the object that created it.2. The instance variable of the object is accessed.When a mouse click occurs, we call setFrame on the ellipse object.egg.setFrame(mouseX - EGG_WIDTH / 2,mouseY – EGG_HEIGHT / 2,EGG_WIDTH, EGG_HEIGHT);The setFrame method just updates the object that stores the ellipse’s position.Then we should tell the applet to repaint itself at the next moment instead of calling the paint method.We do that by calling the repaint method, which causes the paint method to be called.repaint();The inner class doesn’t have a method repaint so the compiler looks in the outer applet class.The compiler then invokes the method on the outer-class object that created the inner-class object- namely, the applet that constructed the listener.Now, let’s us put all the pieces together.import java.applet.Applet;import java.awt.Graphics;import java.awt.Graphics2D;import java.event.MouseEvent;import java.event.MouseAdapter;import java.geom.Ellipse2D;public class EggApplet extends Applet{ public EggApplet(){ egg = new Ellipse2D.Double(0, 0, EGG_WIDTH, EGG_HEIGHT);MouseClickListener listener = new MouseClickListener();addMouseListerner(listener);}public void paint(Graphics g){ Graphics2D g2 = (Graphics2D) g;g2.draw(egg);}private Ellipse2D.Double egg;private static final double EGG_WIDTH = 30;private static final double EGG_HEIGHT = 50;// inner class definitionprivate class MouseClickListener extends MouseAdapter{ public void mouseClicked(MouseEvent event){ int mouseX = event.getX();int mouseY = event.getY();// move the ellipse to (mouseX, mouseY)egg.setFrame(mouseX – EGG_WIDTH / 2,mouseY – EGG_HEIGHT / 2, EGG_WIDTH,EGG_HEIGHT);repaint();}}}Frame WindowsWe can write regular graphical programs in Java that do not run inside a browser or the applet viewer.Every graphical program puts up one or more frame windows.A frame window has a border and a title bar.To show a frame, we use the Jframe class in the javax.swing package.We will use Swing for all graphical user interface, but Swing uses other parts of the AWT, such as parts for drawing graphical shapes and handling events.So, we will continue to use some classes from the java.awt package.The javax package name denotes a standard extension of Java.We specify the size of a frame window with the setSize method of the JFrame class.By default, frames have a size of 0x0 pixels.We can call the setTitle method to set the title.We then invoke the show method to display the frame.import javax.swing.JFrame;public class FrameTest1{ public static void main(String[] agrs){ EmptyFrame frame = new EmptyFrame();frame.setTitle(“Frame Test”);frame.show();}}class EmptyFrame extends JFrame{ public EmptyFrame(){ final int DEFAULT_FRAME_WIDTH = 300;final int DEFAULT_FRAME_HEIGHT = 300;setSize(DEFAULT_FRAME_WIDTH,DEFAULT_FRAME_HEIGHT);}}Unlike applet, graphical applications have a main method.The main method constructs an EmptyFrame object, calls show, and then exits.Even though the main method exits, the program is still running.The frame window stays on the screen, and we move, resize, and so on.This is an important difference between console programs and graphical programs.Once we show a frame window, the program starts a new thread of execution that displays the graphical user interface.When the main method is finished, the main thread is completed, but the Java program does not yet terminate, because the user interface thread is still running.We must manually kill the program by executing the statementSystem.exit(0);The problem is when to execute this statement.We want to exit the program when the user clicks the “close” icon in the title bar.So we must install an event handler that is called when the user clicks on the close icon.To find out when the user closes a window, we must listen to window events.Seven kinds of window events can occur:A window has just opened for the first time.A window has just closed as a result of the dispose method.A window has just been activated.A window has just been deactivated.A window is being iconified (by clicking on the “minimize” icon).A window is being deiconified.A window is being closed by the user (by clicking on the “close” icon).To listen to these events, we must add a window listener object to the frame.A window listener object must implement the WindowListener interface.The Jframe superclass already listens to them and knows how to deal with them.public interface WindowListener{ void windowOpened(WindowEvent e);void windowClosed(WindowEvent e);void windowActivated(WindowEvent e);void windowDeactivated(WindowEvent e);void windowIconified(WindowEvent e);void windowDeiconified(WindowEvent e);void windowClosing(WindowEvent e);}There is a convenience class called WindowAdapter with all seven methods implemented to do nothing.See an example in the following program.// Program: FrameTest2.javaimport java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JFrame;public class FrameTest2{ public static void main(String[] agrs){ EmptyFrame frame = new EmptyFrame();frame.setTitle(“Close me!”);frame.show();}}class EmptyFrame extends JFrame{ public EmptyFrame(){ final int DEFAULT_FRAME_WIDTH = 300;final int DEFAULT_FRAME_HEIGHT = 300;setSize(DEFAULT_FRAME_WIDTH,DEFAULT_FRAME_HEIGHT);WindowCloser listener = new WindowCloser();addWindowListener(listener);}private class WindowCloser extends WindowAdapter{ public void windowClosing(WindowEvent event){ System.exit(0);}}}Adding User Interface Components to a FrameFrames have been designed to arrange user interface components such as buttons, menus, scroll bars, and so on.To draw graphics in a frame, we should draw them onto a separate component and add that component to the frame.The Swing user interface toolkit provides a special component, called JPanel, for this purpose.A JPanel is completely blank, and we can draw whatever we like on it.To draw on a JPanel, we override the paintComponent method.When implementing our own paintComponent method, we must call the paintComponent method of the superclass.public class MyPanel extends JPanel{ public void paintComponent(Graphics g){ super.paintComponent(g);Graphics2D g2 = (Graphics2D) g;…}}To add the panel to a Jframe, we need to know more about the structure of the frame surface.The surface of a Swing frame is covered with four panes.Three of them, namely the root pane, the layered pane, and the glass pane are of no interest.The glass pane is transparent, and its purpose is to capture mouse events.The layered pane holds the menu bar and the content bar together.The root pane holds the glass pane and the layered pane.We need to know about the content pane, which holds the components that we want to display in the window.To add a component to the content pane of a frame, we must get a reference to the content pane object by calling the getContentPane method.This method returns a reference of type Container.A container is a window object that can contain other components.We need to specify both the component that we want to add and the location where we want to add the component.We specify locations in a border layout as one of the five strings “Center”, “North”, “South”, “East”, or “West”.class MyFrame extends JFrame{ public MyFrame(){ MyPanel panel = new MyPanel();Container contentPane = getContentPane();contentPane.add(panel, “Center”);…}…}// MyPanel class definitionpublic class MyPanel extends JPanel{ public void paintComponent(Graphics g){ super.paintComponent(g);Graphics2D g2 = (Graphics2D) g;…}}Reading Text InputWe will learn how to add a text field to a frame and how to read what the user types into it.We can add the text field to a frame by creating a JTextField object and add it to the content pane:class MyFrame extends JFrame{ private JTextField textField;public MyFrame(){ textField = new JTextField();Container contentPane = getContentPane();contentPane.add(textField, “South”);}}When the user hits the Enter key inside a text field, the text field generates an action event.Listening to an action event can be done by installing the ActionListener interface.public interface ActionListener{ public void actionPerformed(ActionEvent event);}The listener is added to the source of the action event (that is the text field).Why we implement the ActionListener interface not the ActionListener Adapter?Because the ActionListener interface has only one method.class MyFrame extends Jframe{ private JTextField textField;public MyFrame(){ textField = new JTextField();textField.addActionListener(newTextFieldListener());Container contentPane = getContentPane();contentPane.add(textField, “South”);}private class TextFieldListener implementsActionListener{ public void actionPerformed(ActionEvent event){ }}}The getText method returns the content that the user enter into the text field.The actionPerformed method retrieves the contents of the text field and processes it.Then we can clear the text field by setting its text to the empty string with the setText method.private class TextFieldListener implements ActionListener{ public void actionPerformed(ActionEvent event){ // get user inputString input = textField.getText();…textField.setText(“”);}}Example: Eggs.javaNow, let’s write a program which asks the user to enter the number, and then we paint as many random eggs as the user requested.We paint the eggs in an EggPanel, which we also add to the content pane of the frame:We also need to keep track of the number of eggs to be drawnimport java.awt.Container;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WIndowAdapter;import java.awt.event.WindowEvent;import java.awt.geom.Ellipse2D;import java.util.Random;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JTextField;public class Eggs{ public static void main(String[] agrs){ EggFrame frame = new EggFrame();frame.setTitle(“Enter number of eggs “);frame.show();}}class EggFrame extends JFrame{ public EggFrame(){ final int DEFAULT_WIDTH = 300;final int DEFAULT_HEIGHT = 300;setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);addWindowListener(new WindowCloser());panel = new EggPanel();textField = new JTextField();textField.addActionListener(new TextFieldListener());Container contentPane = getContentPane();contentPane.add(panel, “Center”);contentPane.add(textField, “South”);}private JTextField textField;private EggPanel panel;private class TextFieldListener implements ActionListener{ public void actionPerformed(ActionEvent event){ String input = textField.getText();panel.setEggCount(Integer.parseInt(input));textField.setText(“”);}}private class WindowCloser extends WindowAdapter{ public void windowClosing(WindowEvent event){System.exit(0);}}}class EggPanel extends Jpanel{ public void paintComponent(Graphics g){ super.paintComponent(g);Graphics2D g2 = (Graphics2D) g;Random generator = new Random();for (int j = 0; j < eggCount; j++){ double x = getWidth() * generator.nextDouble();double y = getHeight() * generator.nextDouble();Ellipse2D.Double egg = new Ellipse2D.Double(x, y, EGG_WIDTH, EGG_HEIGHT);g2.draw(egg);}}public void setEggCount(int count){ eggCount = count;repaint();}private int eggCount;private static final double EGG_WIDTH = 30;private static final double EGG_HEIGHT = 50;} |
|
|
|
by Pizzler contact us at Pizzler@gmail.com |
||