420 likes | 532 Views
CE203 - Application Programming. Part 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):
E N D
CE203 - Application Programming Part 1 CE203 Part 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{ ...} CE203 Part 1
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. CE203 Part 1
Java Applets 3 import javax.swing.*; // for JAppletimport 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); }} CE203 Part 1
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 incorrectlyif it is omitted, so it is good practice to always include such a call as the first line of the method. CE203 Part 1
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 appletviewermyapplet.html (in fact, IDEs like IntelliJ incorporate all this) CE203 Part 1
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> CE203 Part 1
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. CE203 Part 1
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); } } CE203 Part 1
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. CE203 Part 1
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. CE203 Part 1
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.) CE203 Part 1
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. CE203 Part 1
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 CE203 Part 1
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. CE203 Part 1
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. CE203 Part 1
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. CE203 Part 1
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); }} " CE203 Part 1
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. CE203 Part 1
Java Applets 19 import javax.swing.*;import java.awt.*; public class Square extends JApplet{ Colorcol = 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 CE203 Part 1
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. CE203 Part 1
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); }} CE203 Part 1
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. CE203 Part 1
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. CE203 Part 1
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. CE203 Part 1
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. ] CE203 Part 1
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. CE203 Part 1
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(); }} CE203 Part 1
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. CE203 Part 1
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. CE203 Part 1
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 }} CE203 Part 1
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. CE203 Part 1
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. CE203 Part 1
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); CE203 Part 1
Handling Multiple Buttons 4 // Square2.java init method continued JPanelbutPanel = 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 CE203 Part 1
Handling Multiple Buttons 5 In the first version of a button-handler class for the multiple-button 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)); CE203 Part 1
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(); }} CE203 Part 1
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. CE203 Part 1
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 }} CE203 Part 1
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. CE203 Part 1
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(); }} CE203 Part 1
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. CE203 Part 1