Session 19

Communicating Windows


CS 2530
Intermediate Computing


An Opening Exercise: Change on Demand

Last time, we created a cannon ball that was blue when rising and red when falling:

    public void move()
    {
      adjustSpeedBy( 0.0, 0.3 );     // record the effect of gravity
    
      if ( yDeltaIsPositive() )      // change color, if necessary
        become( Color.red );
      else
        become( Color.blue );
    
      super.move();                  // and update my position
    }

Today, let's add to our cannon game a button that lets the user change the color of the cannonball from blue to red to yellow to blue, and so on. Place the button on the lefthand side of the window.

What changes do we have to make to the frame class?

We need the same items we need for the fire button:

But what will the listener do? This question leads us to...

What changes do we have to make to the cannonball class?

We need to subtract one behavior and add another:

(Why not let CannonGameFrame change the color of the ball directly? You know...)

Deleting the rising/falling code means that we can know longer satisfy the request from last session. Maybe we should have put that behavior in a subclass instead of editing the existing class? So, I move last session's behavior to a RisingFallingCannonBall class.

Adding a nextColor() method to the class means that all users of CannonBall will have access to this behavior. That isn't so bad. So we add the method to the existing CannonBall class. That requires -- finally -- adding a color() accessor to the Disk class.

This works. But it isn't very elegant. Can you think of a better way to implement this idea?

Now we know what the listener in the CannonGameFrame needs to do. And we run...

Uh oh. Our button is strangely wide and obstructs our view of the cannon, and the message. Soon we will learn a way to fix this problem by giving our frame a smarter "layout manager". What can we do in the meantime?



Communicating Windows

Here is what I'd like to be able to do:

As someone once earned $500 on Jeopardy! for saying, a picture is worth a 1000 words. Well, "What is 'a picture is worth a 1000 words'?" So...

the initial configuration of two communicating windows

... and then...

the communicating windows after a few button presses

Let's write a Java program to do this. To make our lives simpler, let's take small steps.

Task 1

What objects do we need?

To what messages do these objects respond?

What instance variable will these objects need?

its immediate neighbor?

Task 2

Now, let's implement the GoButton listener. It ties most of the program together. What commitments does your listener require of the communication window class?

Here is one way we might do this:

    private class GoButtonListener implements ActionListener
    {
      public void actionPerformed (ActionEvent e)
      {
        buttonPressCount++;
        if ( partner != null )
          partner.write( "Someone pressed "   + name             +
                         "'s button for the " + buttonPressCount +
                         "th time!" );
      }
    }

Would it be better to pass only the name and buttonPressCount, and let the receiver construct the display string?

Would it be better to send an increment() message, and let the receiver take care of the counter and display string?

Both the sender and receiver are the instances of the same class. Given that, does this decision matter at all?

Task 3

Next, let's implement the constructor for the window...

Constructors are pretty simple. They initialize the instance variables. In frames, they place active components and add event listeners to those components.

Task 4

Finally, let's implement the remaining public methods for the window...

There aren't many, and they are simple. The button listener carries most of the load in this object.

Now all we need is a driver class and we are ready to run. Note the use of command-line arguments to give the windows names. We could, of course, hard-code specific names if we wanted.

Could we have three windows talking to each other in a cyle? Let's try. Yep!



Associations Among Objects

We have now seen three kinds of relationships that two objects can have with one another.

The most common is composition. A Ball contains an xDelta value. An instance of Color is a part of a Disk.

Most instance variables up to today have stored component objects or values. But CommunicationWindows are different. One windown can't be "part" of another in the way we usually mean.

The new kind of relationship is the association. A One CommunicationWindow is associated with another CommunicationWindow. The two objects must interact with each other in order to do their jobs.

Before today, we had created one other association: A BoundedBall interacts with the Frame that contains it.

There is a third kind of relationship that is not recorded in an instance variable. Some objects are like others in a particular way.

This is inheritance. A MovableBall is a kind of Ball. A CommunicationWindow is a Frame.

These names can give us more vocabulary when designing and our programs.



On Homework 6

... simplest. Don't be afraid of the problem. Simple ideas usually lead to simple code. (Or should).

... hide implementation of collection. If we want to change...

... extra credit. My Neighbors can return an "EndCell" that makes the null check unnecessary.



Wrap Up



Eugene Wallingford ..... wallingf@cs.uni.edu ..... October 23, 2012