Session 11 Border Layout, using Panels, Introduction to PinBallGame An Exercise Add to our CannonWorld a button that allows the user to change the color of the cannonball from blue to red to yellow to blue.... Place the button on the lefthand side of the window. An Exercise Place the button on the left-hand side of the window. public CannonWorld() { ... Button changeColor = new Button( "change ball color" ); changeColor.addActionListener( new ChangeColorButtonListener() ); add( "West", changeColor ); } Steps to the solution: 1. Add a button to the CannonWorld. 2. Add a listener class to CannonWorld. The listener’s actionPerformed method needs to tell the ball to take the next color. I could have written an if expression that toggles the colors in sequence, but... • Shouldn’t the ball be controlling its own color, rather than the application using the ball? So I decided to have the CannonBall respond to a nextColor() message and toggle its own color. More on a Solution to the Exercise The next question is, do I add a nextColor() method directly to the CannonBall class, or do I create a subclass? In general, if we need a new kind of object, then we should create a new kinds of object. (If a particular method turns out to be more generally useful than we anticipate, then we can always refactor the solution so that the method lives higher in the class hierarchy.) So: 3. Implement a ChangingCannonBall class. 4. Use instances of ChangingCannonBall in the CannonWorld. Layout Managers • Frame is a subclass of the Container class – so it can hold objects such as buttons, scroll bars, etc. – layout manager assigns locations to these objects within the container – the default LayoutManager is BorderLayout North West Center South East Layout Managers • Five standard types of layout managers: – BorderLayout – GridLayout - creates an rectangular array of components – FlowLayout - places components in rows left to right, top to bottom – CardLayout - stacks components vertically with only one visible at any one time – GridBagLayout - most general, but most complex. It allows for a nonuniform grid of squares with components placed in various positions within each square. Using Panels with BorderLayout • BorderLayout seems very restrictive, but you can use a panel to hold several components in each “direction”. Class Interaction Relationships between classes: 1. composition – A Ball contains a Color. – An instance of Color is a part of a Ball. 2. inheritance – A MovableBall is a kind of Ball. – A CannonWorld is a kind of Frame. 3. association – A BoundedBall interacts with the Frame that contains it. – A CannonWorld interacts with a ColorWheel. Pinball Game Construction Kit • Study a cleaned up and refactored version of Budd’s code from Section 7.1 • Construct a list of three questions (to turn in) that you have about this code. • Your questions can be about how it works, what some piece of code in the program does, or even whey the code is written in a particular way. Some cool new features • Replaced the fire button with a mouse event. • Multiple balls can be in the air at once. • Control is no longer in the paint method. • But before we talk about what Budd did well… Say It Once and Only Once! In the interest of simplifying the number of files we need to run a program, Budd has repeated code that can be reused by inheritance (figure 7.3, p 102). Gravity affects a PinBall in the same way that it affects a CannonBall. The only differences between a PinBall and a CannonBall are its size and its initial trajectory. So, we can say: public class PinBall extends CannonBall { public PinBall( int sx, int sy ) { super( sx, sy, 10,-2 + Math.random()/4, -15 ); } } Inheritance makes our job easier—as well as isolating repeated code. Looks the same, but it’s not. • Replaced the fire button with a mouse event. • Multiple balls can be in the air at once. • Control is no longer in the paint method. Handling Mouse Events The CannonWorld handles only events that are generated by the active components — a button and a slider — that we added to it. More generally, though, we will want to trap and respond to any mouse action, anywhere within the frame. Any listener that wishes to monitor mouse activity must implement the MouseListener interface: public interface MouseListener { public void mouseClicked ( MouseEvent e ); public void mouseEntered ( MouseEvent e ); public void mouseExited ( MouseEvent e ); public void mousePressed ( MouseEvent e ); public void mouseReleased( MouseEvent e ); } The MouseListener interface is part of the package java.awt.event. It specifies what an object must do to be a mouse listener within the Java Event Model. How the MouseListener works. Think back to how we implemented Button listeners: private class FireButtonListener implements ActionListener { We can do a similar thing for MouseListeners… private class PinballGameListener implements MouseListener{ However, to implement an interface, the Java language insists that the programmer provide a definition for all operations. MouseAdapter to the rescue • To simplify this process, the Java library provides a simple class named Mouse Adapter. The class MouseAdapter implements the MouseListener interface, but uses an empty method for each method. • Rather than implement a MouseListener, we may choose to implement a MouseAdapter. (Let’s go back to the code (also p 104)) Mouse Events in the Pin Ball Game In the PinBallGame class, we have the following class relationship: MouseListener ^ | | implements | MouseAdapter ^ | | extends | MouseKeeper • What does a MouseKeeper do? • What does a MouseKeeper do? – If the mouse is pressed in the“shooting area”, then it creates and launches a new pinball. • What does a MouseAdapter do? • What does a MouseAdapter do? – Nothing, in response to any sort of mouse event. • Why do you suppose that Java’s creators call it an “adapter”? • Why do you suppose that Java’s creators call it an “adapter”? – They use a common design from the world as an analogy. • Why do you suppose Java’s creators bothered to define the MouseListener interface? Why not have everyone extend MouseAdapter? • Why do you suppose Java’s creators bothered to define the MouseListener interface? Why not have everyone extend MouseAdapter? – Inheritance is not free. Why force programmers who plan to implement most or all of the interface to pay the extra price?