CPSC 170 Lab 3
Sorting and Mouse Events

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

Sorting

File IntegerList.java contains a Java class representing a list of integers. Save this file to your directory, open it, and study it to be sure you understand it. The following public methods are provided:

File IntegerListTest.java contains a Java program that provides menu-driven testing for the IntegerList class. It creates an empty list of integers and lets you perform various operations on it. Save this file to your directory as well, then compile and run IntegerListTest to see how it works. Add a few integers to the list, then print the list. Then fill the list with random integers and print it again. Now try to add another integer -- it won't let you, as the list is already full.

Modify the code in these files as follows:

  1. Add a method void sortIncreasing() to the IntegerList class that uses selection sort to sort the list into increasing order. You may wish to refer to the code for selection sort in Listing 9.9 of the text, but instead of including all of the sorting code inside the loop in the body of sortIncreasing, write and call the following two methods:

    As we discussed in class, your loop now just contains calls to these two methods. Note that you'll have to save the value returned when you call the first method to pass to the second method.

    Add an option to the menu in IntegerListTest to test your new method.

  2. Add a method void sortDecreasing() to the IntegerList class that uses insertion sort to sort the list into decreasing order. You may wish to refer to the code for insertion sort in Listing 9.9 of the text (but note that it sorts into increasing order, not decreasing).

    Add an option to the menu in IntegerListTest to test your new method.

A Sorted Integer List

Now write a class SortedIntegerList that extends IntegerList. SortedIntegerList should be just like IntegerList except that its elements should always be sorted. This means that when the user chooses to add an element, it should be put into its sorted place, not just at the end. Similarly, when the user chooses to fill the array with random elements, they should be in sorted order. This means that SortedIntegerList must override the add and randomize methods of the IntegerList class. Think carefully about how to implement these new methods. For example, you could implement the new add method by writing all new code, or you could use methods of the IntegerList class to first add the element, and then sort the resulting array. This way your new method is just two calls, and it doesn't even have to access the instance variables of the superclass.

To test your class, copy IntegerListTest.java into SortedIntegerListTest.java and modify it to operate on a SortedIntegerList. Choose a variety of options until you are convinced that your code works correctly.

Print SortedIntegerList.java and IntegerList.java to turn in.

Mouse Events

You have written Java programs that respond to GUI events -- a user pressing a button, checking a box, etc. Programs can also respond to mouse events -- moving and clicking the mouse -- that are not tied to any particular GUI component. Java divides these into two categories: mouse events and mouse motion events. A MouseListener (a class that implements the MouseListener interface) must provide bodies for methods corresponding to each of the mouse events. A MouseMotionListener (implementing the MouseMotionListener interface) must provide bodies for methods corresponding to each of the mouse motion events. These events are described in section 7.9 of the text.

  1. File MousePlay.java contains a program that displays a message saying when the mouse button is pressed and released. It uses MousePlayPanel.java to define the JPanel that is actually displayed. Save these files to your directory, run MousePlay to see how it works, and open MousePlayPanel in emacs. Note that MousePlayPanel has an inner class MousePlayListener that implements MouseListener by giving bodies for the five MouseListener methods. Even though nothing is done when the mouse is clicked or when it enters or exits, those methods still appear with empty bodies -- this is required for the MouseListener interface to be implemented.

    Modify MousePlayPanel so that it also prints appropriate messages when the mouse is clicked, when it enters the panel, and when it exits. Play with the resulting program until you understand how the mouse events are generated.

  2. Files Dots.java and DotsPanel.java contain revised versions of the code in listings 7.18 and 7.19 in the text. Dots draws a dot every time the uses presses the mouse button; only the current dot is shown in the revised version. Save these files to your directory and run Dots to see how it works. Then modify DotsPanel as follows:
    1. Make the dots that appear alternately red and green. To do this, you will need to make the following changes:
      • Add an instance variable to hold the dot color.
      • Add an instance variable to count the number of dots that have been drawn.
      • When the mouse is pressed, in addition to setting the draw point you need to update the counter and change the dot color to green if the counter is odd, to red if it is even. Then call repaint.
    2. Modify your code so that the dot is drawn where the mouse is released, not where it is pressed.

    Print DotsPanel.java to turn in.

  3. 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
        else
           move the circle to the presspoint
      
        repaint
      

    4. Add bodies for the mouseEntered and mouseExited methods so that when the mouse enters the applet 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.