Introduction to Software Engineering

Download Report

Transcript Introduction to Software Engineering

CE203 - Application Programming
Part 1
Autumn 2014
CE203 Part 1
1
Java Applets 1
Applets are Java programs that are designed to run in an
HTML browser. Any user-defined applet must be defined as
a subclass of the library class JApplet (or the class Applet,
its predecessor in Java 1.1):
import javax.swing.*; // for JApplet
public class Greeting extends JApplet
{ ...
}
Autumn 2014
CE203 Part 1
2
Java Applets 2
When an HTML browser visits a page containing the applet
the applet container (a program running in the browser) will
create an applet object and display it on the page. An applet
class does not have a main method since the container
effectively plays this role.
When the applet is displayed its paint method will be called
– a default one inherited from the JApplet class will be used
if the class has no such method.
The paint method takes an argument of type Graphics – we
can apply methods to this argument to draw items on the
applet.
Autumn 2014
CE203 Part 1
3
Java Applets 3
import javax.swing.*; // for JApplet
import java.awt.*;
// for Graphics
public class Greeting extends JApplet
{ public void paint(Graphics g)
{ super.paint(g);
g.drawString("Hello!", 20, 20);
// left baseline of string at (20,20)
g.setColor(Color.blue);
g.drawRect(50, 100, 40, 30);
// top left (50,100),
// width 40, height 30
g.fillRect(120, 100, 30, 40);
}
}
Autumn 2014
CE203 Part 1
4
Java Applets 4
The co-ordinates for the Graphics methods are measured in
pixels with (0,0) being the top left corner.
The setColor method specifies the colour for all subsequent
items to be drawn.
A paint method should normally start with a call to the
inherited method; in a simple example such as this one the
use of super.paint(g) is not actually needed but more
complicated applets could be displayed incorrectly if it is
omitted, so it is good practice to always include such a call as
the first line of the method.
Autumn 2014
CE203 Part 1
5
Java Applets 5
Since applets do not have a main method, we cannot run them
using the java command; they must be embedded into an
HTML page. The simplest page we could use is
<HTML>
<APPLET CODE="Greeting.class">
</APPLET>
</HTML>
The page may be viewed using a browser such as Internet
Explorer but during development it is more convenient to use
the JDK tool appletviewer. Assuming the above HTML is
in a file called myapplet.html we would simply type
appletviewer myapplet.html
(in fact, IDEs like IntelliJ incorporate all this)
Autumn 2014
CE203 Part 1
6
Java Applets 6
The size of the applet may be specified in the HTML file (if it
is not specified the browser will use a default size):
<HTML>
<APPLET CODE="Greeting.class"
WIDTH=200 HEIGHT=150>
</APPLET>
</HTML>
Autumn 2014
CE203 Part 1
7
Java Applets 7
An applet’s paint method can be called more than once
since it may be necessary to update or refresh the display
later in the applet’s lifetime.
Hence any initialisation tasks that are to be performed only
once should not be placed in this method.
The JApplet class has a method called init which is called
once only, before the first call to paint, so if initialisation is
to be performed it should be placed in an init method in our
class to replace the inherited one (which does nothing).
If we wished to allow our greeting applet to be capable of
displaying strings other than “Hello” we should store the
string in a variable initialised as on the next slide.
Autumn 2014
CE203 Part 1
8
Java Applets 8
import javax.swing.*;
import java.awt.*;
public class Greeting2 extends JApplet
{ private String s;
public void init()
{ s = "Hello";
}
public void paint(Graphics g)
{ super.paint(g);
g.drawString(s, 20, 20);
g.setColor(Color.blue);
g.drawRect(50, 100, 40, 30);
g.fillRect(120, 100, 30, 40);
}
}
Autumn 2014
CE203 Part 1
9
Java Applets 9
In addition to graphical items drawn by applying methods to
a Graphics object an applet may contain components such
as text fields, labels, buttons and menus.
If we wish to use a graphical display on an applet with such
components we should ensure that the graphical items do not
interfere with the components. Careful positioning using
coordinates will not be sufficient since components may
move if the window is resized. Hence, instead of drawing the
graphical items directly onto the applet using a paint
method, we should add a component called a panel and draw
them on that.
Autumn 2014
CE203 Part 1
10
Java Applets 10
Components to be placed on an applet must be added to its
content pane, their positions being determined by a layout
manager.
The default manager for applets is BorderLayout in which
the applet may have a central component and one on each of
the four borders, with each component being placed in a
chosen position. Any components placed on the borders will
occupy as much space as is needed for its contents; the
central component will occupy all remaining space.
Autumn 2014
CE203 Part 1
11
Java Applets 11
If the BorderLayout manager is being used we must supply
the position as a second argument to this method using one of
the constant static variables NORTH, SOUTH, EAST, WEST and
CENTER from the BorderLayout class.
(Note: If you use pre-Java-5 code, you will notice that to add
a component to an applet it was necessary to first obtain the
content pane using the getContentPane method from the
JApplet class and then use its add method. This is no longer
needed.)
Autumn 2014
CE203 Part 1
12
Java Applets 12
We shall demonstrate the addition of components to an applet
by modifying our original applet so that the string is
displayed as a label at the top of the applet and the drawing is
performed on a panel which will occupy the rest of the space.
The addition of components to the applet should be done
once only and hence should be placed in the init method.
The panel must be an object of the class JPanel – since we
are going to draw on it we will need to write a painting
method to replace the default one so we need to define a new
subclass of JPanel.
Autumn 2014
CE203 Part 1
13
Java Applets 13
import javax.swing.*;
import java.awt.*;
public class Greeting3 extends JApplet
{ public void init()
{ JLabel label = new JLabel("Hello");
GreetingPanel panel =
new GreetingPanel();
add(label, BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
}
}
// still need to define GreetingPanel
Autumn 2014
CE203 Part 1
14
Java Applets 14
Note that in this simple example it was not necessary to
declare variables for the label and panel; we could have used
code such as
add(new JLabel("Hello"),
BorderLayout.NORTH);
add(new GreetingPanel(),
BorderLayout.CENTER);
However, in any non-trivial applet we would want to be able
to access the components later in the applet’s lifetime, so in
order to make our class adaptable it is sensible to use the
variables.
Autumn 2014
CE203 Part 1
15
Java Applets 15
Since the panel was placed in the centre components it will
occupy all of the space not used by the label. If we had placed
the panel as one of the border components it would have been
necessary to give it an explicit size, as otherwise (since its
contents are not components with sizes) it would be given
minimal size and the rectangles would be drawn outside its
boundaries and hence not be visible.
Autumn 2014
CE203 Part 1
16
Java Applets 16
We must now define the GreetingPanel class; as already
specified it should be a subclass of JPanel.
Since a file may contain only one public class this second
class will not be declared as public.
Instead of a paint method, the JPanel class has a
paintComponent method with an argument of type
Graphics, so we need to write our own version to replace the
default inherited one – in order to work correctly a
paintComponent method should always start with a call to
the inherited method.
Autumn 2014
CE203 Part 1
17
Java Applets 17
// Greeting3.java continued
class GreetingPanel extends JPanel
{ public void paintComponent(Graphics g)
{ super.paintComponent(g);
g.setColor(Color.blue);
"
g.drawRect(50, 100, 40, 30);
g.fillRect(120, 100, 30, 40);
}
}
Autumn 2014
CE203 Part 1
18
Java Applets 18
We now wish to commence the development of an interactive
applet.
The applet will display a square and have a button that can be
used to change the colour of the square.
The square will be drawn on a panel at the centre of the
applet.
The button, of type JButton, will be placed at the bottom of
the applet using BorderLayout.SOUTH. The JButton class
has a constructor with one argument that allows us to specify
the string to be displayed on the button.
Autumn 2014
CE203 Part 1
19
Java Applets 19
import javax.swing.*;
import java.awt.*;
public class Square extends JApplet
{ Color col = Color.red;
public void init()
{ JButton but = new JButton("Press me");
SquarePanel panel =
new SquarePanel(this);
add(but, BorderLayout.SOUTH);
add(panel, BorderLayout.CENTER);
}
}
// continued on slide 22
Autumn 2014
CE203 Part 1
20
Java Applets 20
The paintComponent method in the SquarePanel class will
need to know the identity of the applet in order to access its
col variable. Hence we must supply this information to the
constructor for the SquarePanel class.
Since the applet object will be created not by our program but
by the applet container we do not have any variable that
refers to the object. However we can refer to it using the
keyword this, which refers to the object to which the
method in which it appears has been applied. Inside the init
method this will therefore refer to our applet object, so we
can use it as the argument to the SquarePanel constructor.
Autumn 2014
CE203 Part 1
21
Java Applets 21
// Square.java continued
class SquarePanel extends JPanel
{ Square theApplet;
SquarePanel(Square app)
{ theApplet = app;
}
public void paintComponent(Graphics g)
{ super.paintComponent(g);
g.setColor(theApplet.col);
g.fillRect(20, 30, 40, 40);
}
}
Autumn 2014
CE203 Part 1
22
Java Applets 22
Although we now have an applet that displays a square and a
button nothing will happen when the button is pressed; we
have not written any code that detects the button-press or
changes the value of the variable col.
In order to do this we need to understand the event-driven
programming model used by the classes in the javax.swing
package.
Autumn 2014
CE203 Part 1
23
Event-Driven Programming 1
In traditional procedural programming a main method calls
other methods, which may themselves call further methods,
so the sequence in which methods are called can be
determined by examining the program or input data.
In event-driven programming, however, after performing
initialisation the program simply waits for events to occur
and responds to them – the programmer must write methods
to be called when particular events occur.
Autumn 2014
CE203 Part 1
24
Event-Driven Programming 2
Java applets use the event-driven model: after the init and
paint methods have been called the applet container will
wait for events to occur. When an event occurs it will call a
method supplied by the writer of the applet. Such methods
must be written in objects that implement an interface known
by the applet container, which must be informed about the
identity of the objects and with which events they are to be
associated.
Autumn 2014
CE203 Part 1
25
Event-Driven Programming 3
When the programmer wishes to respond to events associated
with a particular component he or she must add an action
listener to that component. This must be an object belonging
to a class that implements the interface ActionListener,
and is added to the component using the method
addActionListener, e.g.
but.addActionListener(new ButtonHandler());
[ There is a similar interface called MouseListener for
mouse events not associated with components. ]
Autumn 2014
CE203 Part 1
26
Event-Driven Programming 4
In order to implement the ActionListener interface a class
must have a public void method called actionPerformed,
with an argument of type ActionEvent. This is the method
that will be called when the event occurs. The argument will
provide information about the event.
We will now provide a button-handler class for the button to
change the colour of the square in our applet. The
actionPerformed method will need to know the identity of
the applet to access its col variable so we will need to
provide a constructor similar to the one in the SquarePanel
class.
Autumn 2014
CE203 Part 1
27
Event-Driven Programming 5
// Square.java continued
class ButtonHandler implements ActionListener
{ Square theApplet;
ButtonHandler(Square app)
{ theApplet = app;
}
public void actionPerformed(ActionEvent e)
{ if (theApplet.col==Color.blue)
theApplet.col = Color.red;
else
theApplet.col = Color.blue;
theApplet.repaint();
}
}
Autumn 2014
CE203 Part 1
28
Event-Driven Programming 6
Simply changing the value of the applet’s col variable has no
effect on the display – it is also necessary to ensure that the
panel’s paintComponent method is called again. We cannot
do this directly since there is no easy way to get hold of an
appropriate argument. Instead we call the repaint method
from the JApplet class. This method clears anything
previously drawn by paint or paintComponent methods
and calls these methods again.
Another option is to apply repaint directly to the panel, but
to do this its identity would have had to have been stored in
an instance variable of the applet class.
Autumn 2014
CE203 Part 1
29
Event-Driven Programming 7
We must now modify the Square class to add the action
listener to the component, remembering that we must pass the
identity of the applet to the ButtonHandler constructor
using this.
We also need to add an extra import statement to the program
– ActionListener and ActionEvent are defined in the
package java.awt.event.
Autumn 2014
CE203 Part 1
30
Event-Driven Programming 8
import javax.swing.*; import java.awt.*;
import java.awt.event.*;
public class Square extends JApplet
{ Color col = Color.red;
public void init()
{ JButton but = new JButton("Press me");
but.addActionListener(
new ButtonHandler(this));
SquarePanel panel =
new SquarePanel(this);
// add components to content pane
// as before
}
}
Autumn 2014
CE203 Part 1
31
Handling Multiple Buttons 1
Many applets will require more than one button. If the
buttons perform unrelated tasks a separate action listener
class should be written for each. However, in many cases,
several buttons will perform similar tasks and it will be
inefficient to write separate action listener classes.
Two approaches are possible: we can create separate objects
for each button, supplying an argument to the constructor to
indicate which is which, or create a single object, in which
case it is necessary to determine in the actionPerformed
method which button has been pressed.
Autumn 2014
CE203 Part 1
32
Handling Multiple Buttons 2
To illustrate the use of the two approaches we will consider
an applet with buttons to change the colour of a square to
specific colours. We shall place the buttons on a panel at the
bottom of the applet, using the default layout manager for a
panel, FlowLayout, in which the components are positioned
from left to right as added, starting new rows whenever
necessary. When using FlowLayout the add method takes
only one argument since no location information is required.
It is not necessary to create a subclass of JPanel for the
button panel since we do not need to write any methods for
this panel.
Autumn 2014
CE203 Part 1
33
Handling Multiple Buttons 3
import javax.swing.*; import java.awt.*;
import java.awt.event.*;
public class Square2 extends JApplet
{ Color col = Color.black;
public void init()
{ JButton butR = new JButton("Red");
JButton butG = new JButton("Green");
JButton butB = new JButton("Blue");
// need to add action listeners
// to buttons
SquarePanel panel =
new SquarePanel(this);
Autumn 2014
CE203 Part 1
34
Handling Multiple Buttons 4
// Square2.java init method continued
JPanel butPanel = new JPanel();
butPanel.add(butR);
butPanel.add(butG);
butPanel.add(butB);
add(butPanel, BorderLayout.SOUTH);
add(panel, BorderLayout.CENTER);
}
}
// SquarePanel class almost same as before
// but using Square2 instead of Square
Autumn 2014
CE203 Part 1
35
Handling Multiple Buttons 5
In the first version of a button-handler class for the multiplebutton applet each button will use a separate handler object;
the objects need to be distinct so we need to supply
information about the button to the constructor. The simplest
way of doing this is to supply as an argument the colour
associated with the button.
The addActionListener calls to be added to the init
method will be of the form
butR.addActionListener(
new ButtonHandler(this, Color.red));
Autumn 2014
CE203 Part 1
36
Handling Multiple Buttons 6
// Square2.java continued
class ButtonHandler implements ActionListener
{ Square2 theApplet;
Color theColor;
ButtonHandler(Square2 app, Color color)
{ theApplet = app;
theColor = color;
}
public void actionPerformed(ActionEvent e)
{ theApplet.col = theColor;
theApplet.repaint();
}
}
Autumn 2014
CE203 Part 1
37
Handling Multiple Buttons 7
In the second version of the button-handler class we will use
a single button-handler object. The actionPerformed
method will have to determine which button has been pressed
so it must have access to the identity of the buttons – hence
they must be declared as instance variables of the applet
class, instead of local variables in the init method.
A single ButtonHandler object will be created and then used
as an argument to all of the calls to addActionListener.
The constructor will have only one argument since the object
needs no button-identity information.
Autumn 2014
CE203 Part 1
38
Handling Multiple Buttons 8
// imports as usual
public class Square3 extends JApplet
{ Color col = Color.black;
JButton butR, butG, butB;
public void init()
{ butR = new JButton("Red");
// etc
ButtonHandler bh =
new ButtonHandler(this);
butR.addActionListener(bh);
// etc
// rest of method as before
}
}
Autumn 2014
CE203 Part 1
39
Handling Multiple Buttons 9
In the actionPerformed method we need to determine the
identity of the button that has been pressed. This information
is stored in the ActionEvent argument that is supplied to the
method by the applet container. To retrieve the information
from the argument we can apply the getSource method,
which returns a reference to the component with which the
event was associated.
Autumn 2014
CE203 Part 1
40
Handling Multiple Buttons 10
// Square3.java continued
class ButtonHandler implements ActionListener
{ Square3 theApplet;
ButtonHandler(Square3 app)
{ theApplet = app;
}
public void actionPerformed(ActionEvent e)
{ if (e.getSource()==theApplet.butR)
theApplet.col = Color.red;
else if // etc
theApplet.repaint();
}
}
Autumn 2014
CE203 Part 1
41
Handling Multiple Buttons 11
For applets similar to the ones we developed the first
approach would probably be chosen since it is easier to adapt
if extra colour buttons are added – only the init method
needs to be modified. If the second approach were chosen it
would be necessary to modify both the init and
actionPerformed methods.
In many applets a switch statement is used in the
actionPerformed method to select the appropriate action.
Extra cases would have to be added for extra buttons. There
would then be no adaptability advantage and the second
approach may be preferred, particularly if there are many
buttons, in order to reduce the number of objects created.
Autumn 2014
CE203 Part 1
42