The run method terminates Dead/Terminates
2. To know if a thread is Daemon or not Boolean x = t.isDaemon();
Ex: - /*Using thread groups*/
class WhyTGroups {
public static void main(String args[ ]) throws Exception
{
Reservation res = new Reservation();
Cancellation can = new Cancellation();
//create a ThreadGroup with name
ThreadGroup tg1 = new ThreadGroup(tg, “Cancellation Group”);
Thread t3 = new Thread(tg1, res, “Third thread”);
Thread t4 = new Thread(tg1, res, “Fourth thread”);
System.out.println(‘Number of threads in a group = ”+tg.activeCount());
//Find parent group of tg1
System.out.println(‘Parent of tg1 = ”+tg1.getParent());
//set maximum priority to tg1 as 7 tg1.setMaxPriority (7);
//know the ThreadGroup of t1 and t2
System.out.println(‘ThreadGroup of t1 = ”+t1.getThreadGroup());
System.out.println(‘ThreadGroup of t2 = ”+t2.getThreadGroup());
//start the threads
class Reservation extends Thread
t1
{
public void run() {
System.out.println(‘I am Reservation thread”);
} }
class Cancellation extends Thread {
public void run() {
System.out.println(‘I am Cancellation thread”);
}}
Event Handling
Introduction
Graphical User Interface systems handle user interaction using an event driven model. That is, the user performs an action such as moving the mouse, pressing a key or releasing one, etc. These all generate events of some kind. A GUI system such as the Java AWT, Microsoft Windows, Motif, or any other windowing system will sit in an event loop waiting for these events to occur. When one does, application code is called in some way to respond to the event.
The way in which application code is called varies between the different windowing systems. In some, the application programmer has to write an event loop handler themselves, and when an event occurs the application has to figure out what to do with it. In other systems some assistance may be given with this, where events are dispatched to graphical objects automatically. When they arrive, application code still has to work out what type of event has occurred. In yet other systems, the application merely needs to register an event handler with an object, and the handler will be called whenever the right event occurs in the right object, without any further need for intervention by the application programmer.
Java in release 1.1 is now up to its third event processing model! The first one - called the ``old'' event model was abandoned before Java left beta stage. It was replaced by the ``new'' event model for Java 1.0. Unfortunately, two things marred this transition to the new model:
• Books had already begun to appear using the old event model, and hardly anyone mentioned the new model.
• The new model didn't work until JDK 1.0.2, so everyone continued to use the old model anyway.
The difference between the old and new models is subtle and depends on a complex interplay of events that belong to the underlying native implementation and the Java events. This was covered in the Java 1.0 version of this book.
Both the old and new models had serious Software Engineering deficiences that led to poor quality code as soon as applications started to grow in scale. A solution to this was already known as the Command Pattern, and this was adopted for the third event model for the Java AWT. The Command Pattern was renamed ``delegation'' by Sun engineers, and forms a much cleaner way of handling events. Basically, it allows the application to register handlers (called listeners) with graphical objects, which are called when suitable events arrive.
There are complex implementation layers and issues arising from the third event model. When the user performs an action such as a keypress, a native code event is generated. This is firstly handled by native code at, say, the Windows or X level. The event may be caught by the native toolkit or ignored. If caught, two things may happen:
• The event may be given to the native GUI object and then to the Java object.
• The event may be given to the Java object and then to the native GUI object.
Which one of these occurs depends on the event type.
When an event is handed to the Java layer, it is changed into a Java event. Java code looks to see if there is an event listener using the third event model. If there is, this is used. If there is not, then the second ``new'' event model is used. Sometimes there is no listener but the third model should be used anyway. This can be forced.
If all this sounds grim, then be reassured: if you only want to do simple things, the delegation event model lets you do them simply. Most of the time you only want to simple things.
Listeners
A listener is registered with an event type for an object. For example, an application can register a key event listener for any Component, or an action event listener for objects such as Button or TextField.
Listeners are where the programmer places application specific code to respond to user events. When a suitable event occurs, an appropriate method on the listener is invoked.
For example, suppose we are building a Web browser. We may have a Back button to return to the previously displayed page. When we click on this Back button, the application will need to reload the last page into the browser window and reset history lists, current URL pointers, etc. This is not GUI code, though it is clearly application code that affects GUI objects as well as other application objects of the browser. The Back function can also be invoked in other ways, such as by a hot-key or by menu selection. Not only is the behavior application specific, but there is more than one way way of invoking this behavior. A listener object encapsulates this behavior, and should be registered with the Back button, the hot-key combination and the menu selection.
When a listener is invoked, it has to be by one of its methods. There could be a standard method such as execute() or by one customised to the event that caused it. The JDK 1.1 has chosen the second method. So if the mouse is clicked in a Button, then an action event is generated (invisibly to most applications), and theactionPerformed() method is called on any action listener. On the other hand, whenever a key is pressed in a Component, then the method keyPressed() is called in any key event listener.
This could have been more simply if simplicity was the only driving force behind this event model:
however, Java Beans imposes extra requirements which lead to these multiple event types.
The methods defined for listeners are done using interfaces. This is an absolutely appropriate use of the interface mechanism. Since listeners contain application code, they will probably have an inheritance based on the application, not on some vagaries of the GUI side. All the listener needs to do is to implement certain methods, so that the internal event handling code can call the right method. So, for example, the ActionListener is defined by
public interface ActionListener extends EventListener { public abstract void actionPerformed(ActionEvent e) }
whereas KeyListener is defined by
public interface KeyListener extends EventListener { public abstract void keyPressed(KeyEvent e);
public abstract void keyReleased(KeyEvent e);
public abstract void keyTyped(KeyEvent e);
}
Implementing Listeners
Since a listener is defined as an interface, any application code inheriting a listener specification must implement its methods. The rest of the listener code is upto the application. Listener methods will usually interact with other objects of the application. Some of these will be GUI objects, some won't. It doesn't really matter. Returning to our browser example, the Back button listener will need to access the URL object to retrieve the previous URL, and the browser display object to show it. One is graphical, the other is not.
Listener objects - just like any object - get knowledge about other objects in three ways
• They create the other objects and store them in local variables.
• The other objects are passed in by the constructor.
• The other objects are set by special methods
Here is a trivial application just to show how listeners are created and used. The application has a Button on the left, a Button on the right and a Label in the middle. The left Button has the label ``Left'', and the right one has the label ``Right'' When either Button is pressed, the text showing in the Label is set to either ``Left'' or ``Right'' i.e. the label of the Button pressed.
import java.awt.Button;
import java.awt.Label;
import java.awt.event.ActionListener;
/**
* This application consists of two Buttons with a Label * between them. When a Button is pressed, its text is * set in the Label
*
* @author Jan Newmarch */
public class DelegateDemo extends Frame { public static void main(String argv[]) {
new SimpleEvent().show();
}
public DelegateDemo() {
// create the GUI objects Button left = new Button("Left");
Button right = new Button("Right");
Label label = new Label("Center");
// set their geometry add(left, "West");
add(right, "East");
add(label, "Center");
pack();
// create a listener and add it to each Button SimpleListener simple = new SetText(label);
left.addActionListener(simple);
right.addActionListener(simple);
} }
/**
* A listener object that is invokded when a Button is activated * It finds the Button's label and sets it in a Label
*/
class SetText implements ActionListener { private Label label;
public SetText(Label l) {
// the listener needs to know the Label it will act on label = l;
}
public void actionPerformed(java.awt.event.ActionEvent e) { // get the label showing in whichever Button was pressed String name = e.getActionCommand();
// set this in the Label object label.setText(name);
} }
AWTEvent
Events that are handled by delegation objects are all subclassed from AWTEvent. If you are familiar with the old or new event models, then you will have used theEvent class in your event handling code. Forget about that class now. It is superceded by AWTEvent. Forget also about all the fields and values that are present inEvent - they are all absent from AWTEvent. The class AWTEvent has only one field, id, and that is protected anyway. The AWTEvent is very simple, and you don't even need to look at it unless you are doing arcane things (which we will do later).
For each type of event that is present in the delegation model, there is a separate class. The classes are divided into two types: low-level input or window events that every GUI object receives, and higher-level semantic events that only have meaning for particular GUI objects. In addition there are low-level window events that are only received by Frame and Dialog. This kind of division of types is not captured
anywhere in the language, rather it is a guide to the programmer.
The low-level events for any Component are
Table 1: Low-level Event Types
Class id
ComponentEvent COMPONENT_MOVED COMPONENT_RESIZED COMPONENT_SHOWN COMPONENT_HIDDEN
FocusEvent FOCUS_GAINED
FOCUS_LOST
KeyEvent KEY_PRESSED
KEY_RELEASED
KEY_TYPED
MouseEvent MOUSE_CLICKED
MOUSE_DRAGGED MOUSE_ENTERED MOUSE_EXITED MOUSE_MOVED MOUSE_PRESSED MOUSE_RELEASED Where are PaintEvent.PAINT etc?
The low-level window events for Frame and Dialog are
Table 2: Low-level Window Event Types
Class id
WindowEvent WINDOW_CLOSED WINDOW_CLOSING WINDOW_DEICONIFIED WINDOW_ICONIFIED WINDOW_OPENED The semantic level events are
Table 3: Semantic Event Types
Class Id
ActionEvent ACTION_PERFORMED AdjustmentEvent ADJUST_VALUE_CHANGED
ItemEvent ITEM_STATE_CHANGED
For the low-level events, the protected id takes on different values to distinguish between the type of event. This value can be found from the event methodgetId(). For the semantic level events, there is only one value for id, so that although getId() will give a value, it isn't really very useful (unless you have subclassed one of these semantic events and have your own extra id values). These values are used by the AWT to call appropriate methods on listeners, and you do not usually need to look at these values.
The semantic events are generated by the following
Table 3: Semantic Event Generation
Event Object Action
ActionEvent Button Click on Button
List Double-click on an item
MenuItem Click on MenuItem
TextField Press <Enter> key AdjustmentEvent Scrollbar Any Scrollbar action
ItemEvent Choice Select an item
List Select or deselect an item
Checkbox ???
CheckboxMenuItem ???
Listeners for Different Events
For each event type that can occur, the application can add event listeners, that have methods invoked when the event occurs. The listeners are defined asinterfaces, so that an actual listener has to
implement these methods. The names of the listener classes are simply derived from the names of the events they handle, except that MouseEvent's have two different types of listener for efficiency reasons.
Table 4: Listeners for Each Event
Event Listener Method
ActionEvent ActionListener actionPerformed()
AdjustmentEvent AdjustmentListener adjustmentValueChanged() ComponentEvent ComponentListener componentResized()
componentMoved() componentShown() componentHidden() FocusEvent FocusListener focusGained()
focusLost()
ItemEvent ItemListener itemStateChanged()
KeyEvent KeyListener keyTyped()
keyPressed() keyReleased() MouseEvent MouseListener mouseClicked()
mouseEntered() mouseExited() mousePressed() mouseReleased() MouseMotionListener mouseDragged()
mouseMoved() WindowEvent WindowListener windowClosed()
windowClosing() windowDeiconified() windowIconified() windowOpened() The elements of this table should be interpreted as follows:
• An ActionListener has been registered with, say, a Button. When the Button is clicked, the method actionPerformed() of the ActionListener will be called with a single parameter:
the ActionEvent that was generated.
• A KeyListener may be registered for key events with, say, a TextField. When a key is pressed, the method keyPressed() of the KeyListener will be called with the KeyEvent as parameter.
When the key is released, the method keyReleased() will be called with a different KeyEvent as parameter, and also, because a key has been pressed and released (i.e. it has been typed), the method keyTyped() is called with a third KeyEvent as parameter.
• Two types of listener may be registered for mouse events: this represents a tradeoff between consistency and efficiency. Consistency would have one mouse listener only. This would cause event tracking for all of the different mouse events. However, tracking mouse motion is costly:
many events are generated as the user moves the mouse around. In network systems such as X Windows, this can often swamp the available bandwidth leading to visible delays in mouse tracking. Since many GUI objects might be interested in mouse clicks but not mouse motion, using two separate listeners improves efficiency.
Registering Listeners
A listener implements one of the interfaces ActionListener, AdjustmentListener, etc. Once created, listeners are registered with GUI objects. Of course, the GUI object has to be capable of generating the right type of event for the listener. Listeners are added to each object by a
suitable add<event>Listener() call. In the simple example we had earlier, this was done for an ActionEvent listener on a Button by
SimpleListener simple = new SimpleListener(label);
left.addActionListener(simple);
The following table lists which objects can have which listener types added:
Table 5: Objects and Listeners for Them
GUI Object Listener
Button ActionListener Choice ItemListener Checkbox ItemListener Component ComponentListener
FocusListener KeyListener MouseListener MouseMotionListener Dialog WindowListener
Frame WindowListener
List ActionListener
ItemListener MenuItem ActionListener Scrollbar AdjustmentListener TextField ActionListener
Note that every GUI object inherits from Component. So every object can have Component, Focus, Key, Mouse and MouseMotion listeners added.
The next sections look at each event type in turn.