Event handling solution

This is a solution to the event handling lab.

Exercise 1

Modify the the Delegate callback method as follows:

  • Introduce a new interface, KeyBoardListener, inherited from the existing interface TextWatcher.
    • The interface to have one method: void onKeyBoardInput()
  • Introduce a new class called KeyPress, a subclass of TextView
    • In Keypress, override the TextView method doWork as indicated below.
  • Modify EventLoop as follows:
    • The class should implement the new interface only
    • Rather than TextView textview being an instance of TextView, have it be an instance of the derived class Keypress.
    • In the simulated event loop capture a character from a keyboard press.
      • If the character is "c":
        • Set the predicate true.
        • Implement the necessary interface method(s).
      • If the character is "q", quit the program.
    • Here is sample output:
      • EventLoop is provided in skeleton form below.

Here is the package and file arrangement you are recommended to use:

  • Create a new package org.wit.callbackexercise.
    • Populate this package with
      • Two new classes:
        • EventLoop
        • Keypress
      • One new interface
        • KeyBoardListener

Here is skeleton code for EventLoop class with hints

package org.wit.callbackexercise;

import java.util.Scanner;

import org.wit.callback.TextView;

//Class to simulate a short-lived event loop
public class EventLoop 
{
  String keyboardInput;
  static Scanner in = new Scanner(System.in);

  public void runloop()
  {
    TextView textview = new Keypress();
    // EventLoop implements KeyBoardListener
    // Consequently "this" a legal parameter here
    textview.addTextChangedListener(...);
    // The simulated event loop
    do
    {
      keyboardInput = keyboard();
      if (keyboardInput.equals("c"))
      {
        textview.setPredicate(true); // the trigger to fire an event
      }
      textview.doWork();//if predicate true then trigger event in doWork
    } while (keyboardInput.equals("q") == false);
    System.out.println("Thanks for your time - bye");
  }

  /*
   * Capture and return a single keyboard character
   */
  public String keyboard()
  {
    String s = "";
    if(in.hasNext())
    {
      s = in.next();
    }
    return s;
  }

  public static void main(String[] args)
  {
    EventLoop obj = new EventLoop();
    obj.runloop();
    in.close();
  }
}

Here is a skeleton of the derived Keypress class:

package org.wit.callbackexercise;

import org.wit.callback.TextView;

public class Keypress extends TextView
{
  public void addKeyBoardListener(KeyBoardListener listener)
  {
    // Save the event object for later use.
    //TODO ...
  }

  // This method will be invoked repeatedly in an event loop
  @Override
  public void doWork()
  {
    // Check the predicate, which is set elsewhere.
    if (somethingHappened)
    {
      // Signal the event by invoking the interface's method.
      //TODO: Invoke: onKeyBoardInput();
      //TODO: Invoke: onTextChanged("Finally - you called back");
      somethingHappened = false;
    }
  }
}

Here are suggested class diagrams for the solution.

Exercise 1 Solution

Create a new package org.wit.callbackexercise in the project event_handling.

  • Add a KeyBoardListener interface.

KeyBoardListener

Here is the specified listener:

package org.wit.callbackexercise;

import org.wit.callback.TextWatcher;

public interface KeyBoardListener extends TextWatcher
{
  void onKeyBoardInput();
}

EventLoop

Modify org.wit.callbackexercise.EventLoop.java:

  • Have EventLoop implement KeyBoardListener:
public class EventLoop implements  KeyBoardListener
  • Add the necessary import statement:
    • import org.wit.callback.TextWatcher;
  • Implement the required override methods:
  @Override
  public void onKeyBoardInput()
  {
    System.out.println("Keyboard input: " + keyboardInput);   
  }

  @Override
  public void onTextChanged(String changedtext)
  {
    System.out.println("Finally - you called back");
  }
  • In EventLoop register a reference to the object whose class implements listener, namely this:
textview.addTextChangedListener(this);

KeyPress

Complete the skeleton code provided: org.wit.callbackexercise.Keypress.java:

  • Save the object for later use:
  public void addKeyBoardListener(KeyBoardListener listener)
  {
    super.textwatcher = listener;
  }

In doWork():

  • Invoke onKeyBoardInput()
((KeyBoardListener)textwatcher).onKeyBoardInput();
  • Invoke onTextChanged
textwatcher.onTextChanged("Finally - you called back");

Here is the complete method:

  @Override
  public void doWork()
  {
    // Check the predicate, which is set elsewhere.
    if (somethingHappened)
    {
      // Signal the event by invoking the interface's method.
      ((KeyBoardListener)textwatcher).onKeyBoardInput();
      textwatcher.onTextChanged("Finally - you called back");
      somethingHappened = false;
    }
  }

We need to make a change to some of the existing code, namely org.wit.callback.TextView:

  • Note that in KeyPress we require access to the super class TextView
    • TextWatcher textwatcher
    • boolean somethingHappened

We can do this in any of the following ways:

  • Declare both fields public
  • Introduce getter methods
  • Declare both fields protected.

Change the fields to protected:

  protected TextWatcher textwatcher;
  protected boolean somethingHappened;

The code should now be error-free.

Test as follows:

  • In the Package Explorer select org.wit.callbackexercise.EventLoop.java
    • Run as Java Application
    • Bring the console window into focus by placing the mouse cursor anywhere within it and pressing the left mouse button.
    • Type the lower case character c and press return.
    • You should see this:
    • Repeat a number of times.
    • The same output should be repeated.
    • To quit enter the lower case character q.

A complete project containing the solution may be downloaded using a link in the next step.

Archives

This is downloadable archive of the solution event handling code: