CPSC 170 Lab 3
More Listeners, GUIs, & Polymorphism

As usual, create a lab3 subdirectory for today's lab, open this document in FireFox, and start emacs.

More Mouse Events

  1. The file Circles.java sets up a GUI that creates and draws a circle as defined in Circle.java of random size and color at each mouse press Each circle replaces the one before it. The code to handle the mouse press and do the drawing is in CirclePanel.java. Save these files to your directory, compile them and run them and experiment with the GUI. Then modify these files as described below.
    1. This program creates a new circle each time -- you can tell because each circle is a different color and size. Write a method void move(Point p) for your Circle class that takes a Point and moves the circle so its center is at that point. Now modify your CirclesListener class (defined inside CirclePanel) so that instead of creating a new circle every time the user presses the mouse, if a circle already exists it moves the existing circle to the point where the user pressed (the "presspoint"). If no circle exists, a new one should be created at the presspoint. So now a circle of the same color and size should move around the screen.

    2. Write a method boolean isInside(Point p) for your Circle class that takes a Point and tells whether it is inside the circle. A point is inside the circle if its distance from the center is less than the radius. Recall that the distance between two points (x1,y1) and (x2,y2) is sqrt((x2-x1)2+(y2-y1)2.

    3. Now modify the mousePressed method of CirclesListener so that the GUI behaves as follows:
      • If there is no circle (i.e., it is null) and the user presses anywhere, a new (random) circle should be drawn at the presspoint.
      • If there is a circle on the screen and the user presses inside that circle, the circle should go away. (Hint: To make the circle go away, set it to null and repaint.)
      • If there is a circle on the screen and the user presses somewhere else, the circle should move to that point (no change from before).
      So the logic for mousePressed should look like this:

        if there is currently no circle
           create a new circle at the presspoint
        else if the click is inside the circle
           make the circle go away
           move the circle to the presspoint

    4. Add bodies for the mouseEntered and mouseExited methods so that when the mouse enters the JPanel the background turns white, and when it exits the background turns blue. Remember that you can set the background color with the setBackground method.

    5. Now modify the code in CirclePanel.java so that a circle is drawn when the user presses a mouse, but the user can drag it around as long as the mouse button is depressed. If the mouse button is released and then pressed again, it deletes or moves the circle as before. You will need to make the following changes:
      1. In the CirclePanel constructor, make the CirclesListener object listen for both mouse events and mouse motion events. Don't create two separate listeners -- use the same object for both.

      2. Make the CirclesListener class implement the MouseMotionListener interface in addition to the MouseListener interface. This requires two steps:
        • Note in the header that CirclesListener implements MouseMotionListener.
        • Add bodies for the two MouseMotionListener methods, mouseDragged and mouseMoved. In mouseDragged, simply move the circle to the point returned by the getPoint method of the MouseEvent and repaint. (Remember that you already wrote a move() method for the Circle class.) Provide an empty body for mouseMoved.

      Print CirclesListener.java and Circle.java to turn in.

  2. The files RubberLines.java and RubberLinesPanel.java implement the code listings (7.20, 7.21) from your textbook. Download these files and execute them to see how they work.
  3. Copy the card class and the PileOfCards class from your lab2 directory.
    At the command prompt if you are in the lab3 directory, you can type
    cp ../lab2/card.java .
    Note: When you open these files in Eclipse, don't forget to change the package name
    Download the file TwoCardPanel.java and CardGame.java and Run the CardGame program to understand how it works (It is pretty similar to last week, except there are two cards)

    We would like to attach a mouse listener to each of the JLabels so that when the mouse clicks on the picture of a card, the program prints out the name of the card. This may seem easy at first, but there are a couple of hurdles that you will have to overcome to make this work nicely. Here is the general idea.

    1. In the CardPanel constructor, make the "CardListener" object and add it to both of the JLabels. In this case, you shouldn't create two separate listeners -- use the same object for both.

    2. In the CardPanel class, create an inner class called CardListener that implements a Mouse Listener.

    3. In the mouseClicked method, determine which of the cards was pressed (hint: getSource) and print it out. What is wrong with this solution? Try to figure out the problem before you implement it. If you can't, that is ok too, try implementing it and see where it goes wrong.

      How do you fix the problem? See if you can think of a solution and then talk to me or the lab assistant to discuss your ideas.

    Checkboxes and Radio Buttons

    Up until now, you hav been creating simple GUIs with panels, textboxes and buttons. Recall that these programs used ActionListeners to carry out certain actions when a button was pressed. In today's exercise you will see two new GUI components (checkboxes and radio buttons) along with their listeners (ItemListeners and ActionListeners respectively).

    The files StyleOptions.java and StyleOptionsPanel.java are adapted from Listings 5.22 and 5.23 of the text. (A variable fontSize is used rather than an integer literal in various instances and the variable style is an instance variable rather than local to the itemStateChanged method). Save these files to your directory and run StyleOptions.java to see how it works. This is the driver; StyleOptionsPanel.java contains the code for the GUI.

    Now you will add a set of 3 radio buttons to let the user choose among three font sizes. The method of adding the radio buttons will be very similar to that in the QuoteOptionPanel class (Listing 5.25 of the text), so study this example before you continue.

    Do the following to add the radio buttons to the GUI:

    1. Declare three objects small, medium, and large of type JRadioButton.

    2. Instantiate the button objects labeling them "Small Font," "Medium Font," "Large Font." Initialize the large font button to true. Set the background color of the buttons to cyan.

    3. Instantiate a button group object and add the buttons to it.

    4. Radio buttons produce action events so you need to add an inner class (name it SizeListener) to implement ActionListener and listen for radio button clicks. The code for actionPerformed can be similar to that in the QuoteListener in Listing 5.25. (Or if you prefer, you can use the isSelected method to see which button was selected instead of getting and checking the source.) You need to set the fontSize variable (use 16 for small, 24 for medium, and 32 for large) in the if statement, then call the setFont method to set the font for the saying object.

    5. In StyleGUI() instantiate a SizeListener and add it to each button. Also add each button to the panel.

    6. Compile and run the program. Note that as the font size changes the checkboxes and buttons re-arrange themselves in the panel. To fix this, you could put each of the major components into separate panels (you don't have to right now). There are also other ways to address this problem that we will address later in the course.


    Consider the game of Monopoly. The game consists of a sequential set of 40 squares containing 28 properties, 6 Action squares (3 "Chance", 3 "Community Chest"), 2 Tax squares, "GO", "Jail", "Free Parking", and "Go To Jail.". The game is played by moving through the set of squares. Every time a player lands of a square, they take a different action, depending on the type of a square. For example, if you land on a "Tax Square", you must pay the bank a certain amount of money, but if you land on an "Action Square" you must draw a card from the appropriate pile and follow the instructions on the card.

    Note that this is a perfect example of polymorphism. Take a deep breath and relax, you are not implementing Monopoly during this lab. However you are going to use polymorphism to describe the gameplay. To accomplish this you should:

    Print your work to turn in.

    HAND IN: