Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
G51PGP
Programming Paradigms
Lecture 008
Inner classes, anonymous classes, Swing worker thread
1
Reminder – subtype polymorphism
public class TestAnimals
{
public static void main(String[] args)
{
Animal[] animals = new Animal[6];
animals[0] = new Bear();
animals[1] = new Mouse();
animals[2] = new Mouse();
animals[3] = new Fish();
animals[4] = new Mouse();
animals[5] = new Bear();
for ( int i = 0 ; i < animals.length ; i++ )
{
System.out.println( "" + animals[i].getName() +
" ... " + animals[i].getNoise() );
}
}
}2
Array of interface or object
references
Create objects and store
in the array
Each must implement
interface or extend class
The functions exist in ‘animal’ class or interface
Subclasses/implementers must provide implementations
Reminder : Interfaces
• Interfaces are just groups of
function declarations
– No implementations for functions
– We say that these functions are abstract
• A class may implement multiple
interfaces
3
Subclass /
Derived class
extends
implements
Superclass/base class
Interface
Base/superclassSub/derived class
public interface Animal
{
String getName();
String getNoise();
}
A class hierarchy
• Some classes are both
sub-classes/derived
classes and
superclasses/base classes
4
Object
Component
Container
JComponent
JPanel
Window
Frame
JFrameJLabel
Abstract classes
• You can have abstract functions in classes
– Used only for implementing in the sub-classes
– E.g. abstract String getName();
• You can have abstract classes
– A class for which you cannot create objects
– E.g. public abstract class Animal { }
• If you add an abstract function to a class, the class must be declared abstract as well
• You can think of interfaces as abstract classes where all of the functions are abstract and there is no member data
– But you use implements rather than extends
– That matters: You can only extend one class, but can implement many interfaces
• We will concentrate on interfaces 5
public interface Animal
{
String getName();
String getNoise();
}
• No need to say public
• No implementations
• No data
• Subclasses need to
implement the interface
• Classes may implement
multiple interfaces
public abstract class Animal
{
public abstract String getName();
public abstract String getNoise();
}
• We could mix abstract and
concrete methods
• We could add data
• Sub-classes need to extend the
class
• Classes can only extend one class
6
Interfaces
Event handlers
• Many window systems are event based
• Someone ‘does something’ and it raised an event for the program to handle– E.g. move the mouse, click on something, close a
window, etc
– More next week on what is picking up the events in Java
• Components can handle events– e.g. mouse move or mouse pressed
• When an event occurs, the components look whether they have an object registered to handle the event– Usually this means giving it an object which implements
the interface and we rely on subtype polymorphism7
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class UsesButton
implements ActionListener
{
public static void main(
String[] args)
{
new UsesButton().go();
new UsesButton().go();
}
// Note: these were made members rather than local variables so that I keep the reference for later use
JFrame frame;
JLabel label;
JButton button;
public void go()
{
frame = new JFrame();
frame.setLayout( new FlowLayout() );
label = new JLabel( "." );
frame.add( label );
button = new JButton("Press Me");
button.addActionListener(this);
frame.add( button );
frame.pack();
frame.setVisible(true);
}
public void actionPerformed(
ActionEvent e)
{
label.setText(label.getText()+".");
frame.pack(); // Label size changed
}
}
8
Example using a JButton
New class: JButton
New interface: ActionListener
New function to add listener
• To handle an event in
Java Swing, we provide
an object which will
handle the event
• We need an object
• The object must
implement a specified
interface
• The object must
implement all of the
functions in the
interface
public class UsesButton
implements ActionListener
{
public static void main( String[] args)
{
new UsesButton().go();
}
public void go()
{ …
button.addActionListener(this);
}
public void actionPerformed(
ActionEvent e)
{
label.setText(label.getText()+".");
frame.pack();
}
}9
Event handlers
ActionListener interface
package java.awt.event;
import java.util.EventListener;
public interface ActionListener extends EventListener
{
/* Invoked when an action occurs. */
public void actionPerformed(ActionEvent e);
}
• This is the real code from the default implementation
• Reformatted, and most of the comments removed10
Listener interfaces and Observer Pattern
• Examples of something called an observer pattern
• You can register multiple listeners
• You can removeActionListener() to remove it again
• Action listeners get added to a list:
public void addActionListener(ActionListener l)
{
listenerList.add(ActionListener.class, l);
}
• Observer pattern:
– Object (subject) maintains a list of dependents (observers) and notifies them of specific events/changes
– Observers register themselves with the subject when they want to start getting notifications, and unregister themselves afterwards 11
Nested/Inner classes
• Nested class: class defined inside another class
• A static nested class is not associated with a specific instance of the class
– static basically means not associated with instance
– It just gets a different name really
– Useful for grouping or hiding implementation classes
– Static means associated with the class as a whole, rather than a specific object (no this reference on functions)
• A non-static nested class is an inner class
– It is associated with a specific instance/object
– It has access to the member data of the surrounding class – very useful at times
12
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class UsesButtonInnerClass
{
public static void main(
String[] args)
{
new UsesButtonInnerClass().go();
new UsesButtonInnerClass().go();
}
// Still members…
JFrame frame;
JLabel label;
JButton button;
class ButtonPressHandler
implements ActionListener
{
public void actionPerformed(
ActionEvent e)
{
label.setText(label.getText()+".");
frame.pack(); // Label size changed
}
}
public void go()
{
frame = new JFrame();
frame.setLayout( new FlowLayout() );
label = new JLabel( "." );
button = new JButton("Press Me");
button.addActionListener(
new ButtonPressHandler());
frame.add( label );
frame.add( button );
frame.pack();
frame.setVisible(true);
}
} 13
Creating and using an inner class
Example2
class ButtonPressHandler
implements ActionListener
{
public void actionPerformed(
ActionEvent e)
{
label.setText(
label.getText()+".");
frame.pack();
}
}
• Inner class
• Defined within the outer class
• Instances can access the members of
the surrounding instance – the one
which created it
public void go()
{
frame = new JFrame();
frame.setLayout(
new FlowLayout() );
label = new JLabel( "." );
frame.add( label );
button = new JButton(
"Press Me");
button.addActionListener(
new ButtonPressHandler());
frame.add( button );
frame.pack();
frame.setVisible(true);
}
14
Key features: new class and listening
JButton button1; // Renamed
JButton button2; // Added
// Rename one handler
// and create a 2nd version
class ButtonPressHandler2
implements ActionListener
{
public void actionPerformed(
ActionEvent e)
{
label.setText( "." );
frame.pack();
}
}
public void go()
{
…
button1 = new JButton("Add");
button1.addActionListener(
new ButtonPressHandler1());
frame.add( button1 );
button2 = new JButton("Clear");
button2.addActionListener(
new ButtonPressHandler2());
frame.add( button2 );
15
Now we can create two buttons…
Example3
MouseListener Interface
public interface MouseListener extends EventListener
{
/* Mouse button clicked (pressed and released) */
public void mouseClicked(MouseEvent e);
/* Mouse button has been pressed */
public void mousePressed(MouseEvent e);
/* Mouse button released */
public void mouseReleased(MouseEvent e);
/* Invoked when the mouse enters a component. */
public void mouseEntered(MouseEvent e);
/* Invoked when the mouse exits a component. */
public void mouseExited(MouseEvent e);
} 16
Using the interface : MyMouseHandler
class MyMouseHandler implements MouseListener
{
public void mouseClicked(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
label.addMouseListener( new MyMouseHandler() );
17
Example4
MouseMotionListener Interface
public interface MouseMotionListener extends EventListener
{
/* Mouse moved when button pressed */
public void mouseDragged(MouseEvent e);
/* Mouse moved when button not pressed */
public void mouseMoved(MouseEvent e);
}
18
Using the interface : MyMouseHandler
class MyMouseMotionHandler implements MouseMotionListener
{
/* Mouse moved when button pressed */
public void mouseDragged(MouseEvent e)
{ System.out.print("D"); }
/* Mouse moved when button not pressed */
public void mouseMoved(MouseEvent e)
{ System.out.print("M"); }
}
label.addMouseMotionListener( new MyMouseMotionHandler() );
19
Example4
Adapters• As interfaces become larger it may be a pain to implement all of the
functions when we only need a few (or one)
• Adapter classes solve this problem for us
• They already implement the interface and provide dummy implementations
for the functions – we just need to implement the ones which will change
class MyMouseHandler implements MouseListener
{
public void mouseClicked(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
class MyMouseHandler extends MouseAdapter
{
public void mouseClicked(MouseEvent e) {}
} 20
Example5
Note: adapter pattern
• Adapter pattern is another design pattern
– We will cover this later
• It is more general than the adapter classes
discussed here
• It converts from one interface to another
• In my opinion, this isn’t exactly what these
adapters are doing – although it sort of is
• Warning: don’t confuse these adapter classes
with the adapter pattern
• Remember this warning when revising21
Anonymous classes
• It is really common to create a inner class which is a subclass of an adapter class, or which implements an interface, and just pass the one object into a function
– You only ever create one object of this class
– You never need to reuse the class
– So why bother giving it a name?
• You can use an anonymous class:
– Add { } and the subclass functions implementation onto the end of the new statement…
new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{ System.out.print("C"); }
});22
Example6
Anonymous class
• You don’t give an anonymous class a name
• You can’t give it an explicit constructor
– What would you call it anyway?
• You can give it member data (member variables)
• Member variables in Java get zeroed or null’ed
– Unlike C/C++ variables
button1.addMouseMotionListener(
new MouseMotionAdapter()
{
int count;
public void mouseDragged(MouseEvent e)
{ System.out.print("D" + (count++) ); }
} );23
Example7
Event Queues
• Events are handled one by one
• Something picks up your event and calls a function which asks your object to handle the event
• Not your own function calling it – your main ends…
public static void main( String[] args)
{
new Example7AnonymousClassTwoListeners().go();
new Example7AnonymousClassTwoListeners().go();
// No more ‘main()’ so main() ends now
}
• … but your program continues to execute….
• … why?
24
Threads
• Threads are lightweight processes
• Your process can have multiple threads running inside it
• They share the same memory (process space)
• You can create your own threads (next lecture)– There are some things that you need to be aware of
– Java provides simple fixes to avoid most problems
– You need to use the fixes though
• Swing creates its own worker thread when you display the first window– You need to understand this
– Swing is not thread-safe – only this worker thread should do any drawing – not your own code!!!
25
Example of main thread doing things…
• Main thread starts with
‘main()’
• When it creates the
window (setVisible())
another thread will start
• Normally main() then
ends
• Here we left main()
running…
26
createGUI()
doOther
Stuff()
Pick up
event
Handle
event
WorkerThreadTest
Warning
• You should not change the GUI from any thread
other than the GUI thread
• The program I just used did so though
– This is very bad
– But we got away with it because nothing else was
doing things
• Concept: thread safety
– A system is thread safe if multiple threads running at
the same time and using it cannot cause problems
– Swing is NOT threadsafe!!!27
Next lecture
• Threads
– InvokeLater for Swing
• Sharing data between threads
– Safely
• Monitors
• Exceptions and exception handling
28