Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
CE203 - Application Programming Part 2 Dr Ian Daly Autumn 2016 CE203 Part 2 1 General notices • Please do attend the labs, this is your opportunity to practice coding with assistance. • Please come to lab1 first (we can overflow into the other labs if we need to). • Test on week 6. – 10% of mark – Multi-choice – Quizzes in the lectures are good practice • Guest lecture: “Databases in the wild” by Wesley Hall, week 7. Autumn 2016 CE203 Part 2 2 Labs this week • The best way to learn to program is to practice. • Labs are your opportunity to get feedback on your progress and help with your programming. • This weeks lab will include a recorded feedback session. – GLAs will give you feedback on your work during the lab – We will record who has met with the GLAs during the lab. – Make sure one of the GLAs notes your attendance. Autumn 2016 CE203 Part 2 3 Learning objectives today • Java applications and graphical user interfaces (GUIs) • Event driven programming • User interfaces – Buttons Autumn 2016 CE203 Part 2 4 Lectures • Lecture notes will be post to orb before the lecture so you can download and follow along. • The lectures include a fair amount of worked code examples. • Feel free to work along on your laptops if you have one. • However, the code is incomplete, I only show the minimum to introduce the concepts, no complete programs. • I can’t help you with code errors during the lectures, this is what the labs are for Autumn 2016 CE203 Part 2 5 Types of Application • • • • • Desktop / Laptop (“traditional”) applications Mobile (Android) applications Console applications Java Applet (being phased out) etc. Autumn 2016 CE203 Part 2 6 Java Graphical User Interfaces 1 Java programs can show graphical user interfaces by using frames. Any application that presents a graphical user interface (GUI) must instantiate a JFrame.: import javax.swing.JFrame; public class Greeting { ... } Autumn 2016 CE203 Part 2 // for JFrame 7 Java Graphical User Interfaces 1 • JFrame: Contains graphical objects – JPanel – Components – Both can hold buttons, labels, text fields etc. Autumn 2016 CE203 Part 2 8 Java Graphical Interfaces 3 An alternative: Java Applets In the process of being phased out. 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 2016 CE203 Part 2 9 Java Graphical Interfaces 4 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 most browsers 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 2016 CE203 Part 2 10 Java Graphical Interfaces 5 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> (apart from the applet tag there are object and embed tags but on the Java API Oracle recommends “to use the applet tag as a consistent way to deploy Java applets across browsers on all platforms”) Autumn 2016 CE203 Part 2 11 Java Graphical Interfaces 6 Desktop applications (unlike applets) require a main method. This serves as the entry point for the application. The main method takes a string array of variable length, which allows command line variables to be sent to the application. The following slide contains a simple ‘hello world’ Java desktop application. Autumn 2016 CE203 Part 2 12 Java Graphical Interfaces 7 Applications import javax.swing.*; // for JFrame public class Greeting { public static void main(String[] args) { JFrame frame = new JFrame(); JLabel label = new JLabel( “Hello world” ); frame.add( label ); frame.setSize( 200, 200 ); frame.setTitle( “Hello” ); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setVisible( true ); } } Autumn 2016 CE203 Part 2 13 Java Graphical Interfaces 8 Elements can be arranged on a frame via JPanels Interface elements can be added directly to the frame or to a JPanel. JButton Jlabel JTextBox JTextArea JToggleButton JRadioButton etc. Autumn 2016 CE203 Part 2 14 Java Graphical Interfaces 9 • Images, shapes etc. can be added to a component via the Graphics object. Coordinates 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. • The paintComponent method can be used to paint shapes and receives an object of type Graphics. • This can be placed in a JFrame by instantiating a Component or a JPanel Autumn 2016 CE203 Part 2 15 Java Graphical Interfaces 10 import javax.swing.*; import java.awt.*; // for Jframe public class Greeting { public static void draw( Graphics g ) { g.setColor( Color.BLUE ); g.fillRect( 10, 10, 50, 50 ); } public static void main(String[] args) { JFrame frame = new JFrame(); JPanel component = new JPanel() { public void paintComponent( Graphics graph ) { draw( graph ); } } frame.add( component ); frame.setSize( 200, 200 ); frame.setTitle( “Hello” ); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setVisible( true ); } } Autumn 2016 CE203 Part 2 16 Java Graphical Interfaces 11 An applications paint or draw methods can be called more than once since it may be necessary to update or refresh the display later in the application’s lifetime. Hence any initialisation tasks that are to be performed only once should not be placed in these methods. For example, if we wished to allow our applications to be capable of displaying multiple strings (not just “Hello world”) we should store the string in a variable initialised as on the next slide. Autumn 2016 CE203 Part 2 17 Java Graphical Interfaces 12 import javax.swing.*; import java.awt.*; public class Greeting { private String s; public static void main(String[] args) { s = "Hello"; . . . Autumn 2016 CE203 Part 2 18 Java Graphical Interfaces 13 Graphical items can be drawn by applying methods to a Graphics object. An application may also contain components such as text fields, labels, buttons and menus. If we wish to combine graphical items and 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 application using a paint method, we should add a component called a JComponent and draw them on that. We can also position components within a panel. Autumn 2016 CE203 Part 2 19 Java Graphical Interfaces 14 Components to be placed on an application must be added to its content pane, their positions being determined by a layout manager. The default manager for applications is BorderLayout in which the application 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 2016 CE203 Part 2 20 Java Graphical Interfaces 15 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. http://coding365.blogspot.co.uk/2012/11/java-exercise-53-demonstrate-border.html Autumn 2016 CE203 Part 2 21 Java Graphical Interfaces 16 Other Layout managers: BoxLayout Components go in a single row / column. FlowLayout Components go in a single row. A new row is started if the container is not wide enough. Default layout manager for Jpanels. (pics from https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html) Autumn 2016 CE203 Part 2 GridLayout Components are equal in size and go in requested rows and columns. 22 Java Graphical Interfaces 17 Many more layout managers available… Check https://docs.oracle.com/javase/tutorial/uiswing/layout/visual. html for details. Autumn 2016 CE203 Part 2 23 Java Graphical Interfaces 18 We shall demonstrate the addition of components to an application by modifying our original application so that the string is displayed as a label at the top of the application and the drawing is performed on a panel which will occupy the rest of the space. The addition of components to the application should be done once only and hence should be placed in the main method. The panel must be an object of the class JPanel Autumn 2016 CE203 Part 2 24 Java Graphical Interfaces 19 import javax.swing.*; import java.awt.*; public class Greeting3 { public void main( String[] args ) { JFrame frame = new JFrame(); JLabel label = new JLabel("Hello world"); JPanel panel = new JPanel(); panel.add( label, BorderLayout.NORTH ); frame.add( panel, BorderLayout.SOUTH ); frame.setSize( 200, 200 ); frame.setTitle( “Hello” ); } } Autumn 2016 // etc. CE203 Part 2 25 Java Graphical Interfaces 20 Label added at north (top) of panel. Panel added at south (bottom) of frame. Autumn 2016 CE203 Part 2 26 Java Graphical Interfaces 21 Use inheritance to create custom frames. Design a sub-class of JFrame Store components as instance variables Initialise in constructor Example on next slide… Autumn 2016 CE203 Part 2 27 Java Graphical Interfaces 22 // Greeting3.java continued public class FilledFrame extends JFrame { private JButton button; private JLabel label; private static final int FRAME_WIDTH = 300; private static final int FRAME_HEIGHT = 300; public FilledFrame() { createComponents(); // Helper method. setSize( FRAME_WIDTH, FRAME_HEIGHT ); } private void createComponents() { button = new JButton( “Click me” ); label = new JLabel( “Hellow world” ); Jpanel panel = new Jpanel(); panel.add( button ); panel.add( label ); add( panel ); } Autumn 2016 CE203 Part 2 28 Java Graphical Interfaces 23 • We can then call this new frame class from main . . public void main( String[] args ) { FilledFrane frame = new FilledFrame(); frame.setTitle( “A frame with two components” ); . . Autumn 2016 CE203 Part 2 29 Java Graphical Interfaces 24 We can also extend the JPanel class to include customised layouts of graphical objects. Since a file may contain only one public class this second class will not be declared as public. 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 2016 CE203 Part 2 30 Java Graphical Interfaces 25 // 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); } } To use… .. GreetingPanel panel = new GreetingPanel(); .. Autumn 2016 CE203 Part 2 31 Java Graphical Interfaces 26 Interactivity We now wish to develop an interactive application. The application 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 application. The button, of type JButton, will be placed at the bottom of the application 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 2016 CE203 Part 2 32 Java Graphical Interfaces 27 import javax.swing.*; import java.awt.*; public class FilledFrame extends JFrame { .. . Color col = Color.red; public void createComponents() { JButton but = new JButton("Press me"); SquarePanel panel = new SquarePanel(this); add(but, BorderLayout.SOUTH); add(panel, BorderLayout.CENTER); } } // continued below Autumn 2016 CE203 Part 2 33 Java Graphical Interfaces 28 paintComponent method in the SquarePanel class will need to know the The identity of the FilledFrame in order to access its col variable. Hence we must supply this information to the constructor for the SquarePanel class. We can do this using the keyword this, which refers to the object to which the method in which it appears has been applied. Note, we can’t use this within the static context, e.g. within the main method, which is why we use the FilledFrame class rather than setup the frame directly within the main function. Autumn 2016 CE203 Part 2 myClass this 34 Java Graphical Interfaces 29 // Square.java continued class SquarePanel extends JPanel { FilledFrame theApp; SquarePanel( FilledFrame app ) { theApp = app; } public void paintComponent( Graphics g ) { super.paintComponent( g ); g.setColor( theApp.col ); g.fillRect( 20, 30, 40, 40 ); } } Autumn 2016 CE203 Part 2 35 Java Graphical Interfaces 30 Although we now have an application 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 2016 CE203 Part 2 36 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 2016 CE203 Part 2 37 Event-Driven Programming 2 Java applications use the event-driven model: after the main and any paint or other initialisation methods have been called the application container will wait for events to occur. When an event occurs it will call a method supplied by the writer of the application. Such methods must be written in objects that implement an interface known by the application container, which must be informed about the identity of the objects and with which events they are to be associated. Autumn 2016 CE203 Part 2 38 Event-Driven Programming 3 Procedural program 1. 2. 3. 4. 5. Initialisation Action 1 Action 2 ….. Exit Autumn 2016 Event-driven program 1. 2. 3. 4. 5. Initialisation Wait for events… If event occurs perform associated action Repeat steps 2-3 until exit action… Exit CE203 Part 2 39 Event-Driven Programming 4 Event handling may be understood via the metaphor of a postman. Suppose we have several letters (messages) and several homes, each with its own address. A postman may deliver messages to addresses via the following algorithm… for each letter in Letters, for each home in Homes, if letter.destination == home.address, deliver( letter to home ); end if end for end for In Java, messages are Events, which are dispatched by Event generators to Listener interfaces. Autumn 2016 CE203 Part 2 40 Event-Driven Programming 5 The Java Event Model Framework Three classes and an interface… EventObject EventListener EventListenerProxy TooManyListenersException (class) (class) (interface) (class) New types of Event can be specified by extending EventObject New classes, that have to be notified when an event occurs, can implement the EventListener interface. Specific types of sub-interfaces for different event categories are named <event category name>Listener e.g. ActionListener is the interface used for events in the Java GUI and new events can be generated by calling addActionListener Classes can be written to broadcast events. Autumn 2016 CE203 Part 2 41 Event-Driven Programming 6 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 2016 CE203 Part 2 42 Event-Driven Programming 7 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. Example: We will now provide a button-handler class for the button to change the colour of the square in our application. The actionPerformed method will need to know the identity of the application to access its col variable so we will need to provide a constructor similar to the one in the SquarePanel class. Autumn 2016 CE203 Part 2 43 Event-Driven Programming 8 // Square.java continued class ButtonHandler implements ActionListener { FilledFrame theApp; ButtonHandler( FilledFrame app ) { theApp = app; } } public void actionPerformed(ActionEvent e) { if (theApp.col==Color.blue) theApp.col = Color.red; else theApp.col = Color.blue; theApp.repaint(); } Autumn 2016 CE203 Part 2 44 Event-Driven Programming 9 Simply changing the value of the application’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 JFrame 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 application class. Autumn 2016 CE203 Part 2 45 Event-Driven Programming 10 We must now modify the FilledFrame class to add the action listener to the component, remembering that we must pass the identity of the FilledFrame 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 2016 CE203 Part 2 46 Event-Driven Programming 11 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class FilledFrame extends JFrame { .. Color col = Color.red; public void createComponent() { JButton but = new JButton("Press me"); but.addActionListener( new ButtonHandler(this)); SquarePanel panel = new SquarePanel(this); // add components to content pane // as before } } Autumn 2016 CE203 Part 2 47 Event-Driven Programming 12 Autumn 2016 CE203 Part 2 48 Event-Driven Programming 13 Summary Event handling allows the application to wait for user / system initiated events. An event handler class should be created (by extending ActionListener or in the more general case EventListener). The public actionPerformed method can than be overwritten to hold the code to be executed when the event occurs. The ActionListner interface is defined in the java.awt.event.* framework Autumn 2016 CE203 Part 2 49 Event-Driven Programming 14 General points - Event handling is done in the same thread as draw operations. Therefore, even handlers should be fast, so as not to make execution appear slow or unresponsive. - Separate threads may be added for more complex operations (more on this at the end of the course). - Good practice in even handling is to implement event handlers in a none public class, this is more secure in large projects. Autumn 2016 CE203 Part 2 50 Handling Multiple Buttons 1 Many applications will require more than one control item (e.g. multiple buttons, menu items, etc.) We consider, as a worked example, the case of multiple buttons. 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: 1) We can instantiate separate objects for each button, supplying an argument to the constructor to indicate which is which, 2) or instantiate a single object, in which case it is necessary to determine in the actionPerformed method which button has been pressed. Autumn 2016 CE203 Part 2 51 Handling Multiple Buttons 2 To illustrate the use of the two approaches we will consider an application 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 application, 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 2016 CE203 Part 2 52 Handling Multiple Buttons 3 In FilledFrame class // Imports and class setup as previously Color col = Color.black; public void createComponents() { 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 2016 CE203 Part 2 53 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); } } Autumn 2016 CE203 Part 2 54 Handling Multiple Buttons 5 In the first version of a button-handler class for the multiplebutton application 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 initialisation method will be of the form butR.addActionListener( new ButtonHandler(this, Color.red)); Autumn 2016 CE203 Part 2 55 Handling Multiple Buttons 6 // Square2.java continued class ButtonHandler implements ActionListener { FilledFrame theApp; Color theColor; ButtonHandler(FilledFrame app, Color color) { theApp = app; theColor = color; } public void actionPerformed(ActionEvent e) { theApp.col = theColor; theApp.repaint(); } } Autumn 2016 CE203 Part 2 56 Handling Multiple Buttons 7 Autumn 2016 CE203 Part 2 57 Handling Multiple Buttons 8 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 FilledFrame class, instead of local variables in the constructor. 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 2016 CE203 Part 2 58 Handling Multiple Buttons 9 // imports as usual public class FlledFrame extends JFrame { Color col = Color.black; JButton butR, butG, butB; } public void createComponents() { butR = new JButton("Red"); // etc ButtonHandler bh = new ButtonHandler(this); butR.addActionListener(bh); // etc // rest of method as before } Autumn 2016 CE203 Part 2 59 Handling Multiple Buttons 10 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 application 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 2016 CE203 Part 2 60 Handling Multiple Buttons 11 // Square3.java continued class ButtonHandler implements ActionListener { FilledFrame theApp; ButtonHandler(FilledFrame app) { theApp = app; } } public void actionPerformed(ActionEvent e) { if( e.getSource()==theApp.butR ) { theApp.col = Color.red; } else if // etc theApp.repaint(); } Autumn 2016 CE203 Part 2 61 Handling Multiple Buttons 12 Summary -Multiple buttons are an example of the general case of multiple similar control options in an application e.g. -Menu items -Keyboard events -Mouse events -etc. -Two approaches are possible: 1) Instantiate separate objects that implement the ActionListener interface for each item (button). 2) Instantiate a single object and determine the event to be performed in the actionPerformed method. Autumn 2016 CE203 Part 2 62 Handling Multiple Buttons 13 For applications 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 initialisation method needs to be modified. If the second approach were chosen it would be necessary to modify both the initialisation and actionPerformed methods. However, note that the first approach is more memory intensive, a new event handler object has to be instantiated for each button. In many applications 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 2016 CE203 Part 2 63 Quiz • A chance to test your knowledge • Practice for assessed tests and exams • Remember: be careful in picking your username. Please do Not use names that could cause offence. kahoot.it Autumn 2016 CE203 Part 2 64 Summary • Today we talked about… – Graphical user interfaces – Event driven programming – Handling multiple buttons • Remember: – This weeks lab includes a signed feedback session. – Attend and get feedback from the GLAs. – Make sure they sign you off the list. Autumn 2016 CE203 Part 2 65 Next week… • • • • • Inheritance Abstract classes Interfaces Java collections framework Vectors Autumn 2016 CE203 Part 2 66