Events


Contents

Introduction

Perhaps the most distinguishing feature of the DoodlePad library is the ease and extent to which it supports event driven programming. All DoodlePad Shape objects as well as the Pad object may be set up to invoke custom methods in response to a wide range of user interaction. For example, you may want the change the fill color of one or more shapes when the user hovers over the shape or clicks the shape with the mouse. Alternatively, you may want to move a Shape in specific direction when the user presses one of the arrow keys. The Pad object implements timer functionality that raises tick events at a user-specified rate. You may want to invoke one or more of your custom methods each time the Pad's timer ticks, which may be accomplished using the Pad's tick event.

By default, all Shape objects as well as Pad objects trigger a wide array of events. But sometimes you don't want a Shape or Pad object to react to events at all, allowing all interactions to be handled by the Shape object or Pad object underneath. For example, imagine a Happy Face made up of a large yellow Oval for the face, two smaller black Ovals for the eyes and an Arc for the smile. You might want the eyes and smile to ignore all mouse interaction so that only the underlying yellow face Oval detects all mouse interaction and triggers mouse events. Another use case occurs when you want to create a button with a label by placing a Text Shape over a RoundRect Shape. In this case you want the Text to ignore all mouse interaction and allow the underlying RoundRect to respond to the mouse. This is easily accomplished by disabling events on your top-level Shapes. Use the setEventsEnabled(...) method to disable or re-enable event triggering for any Shape object or any Pad object.

This ability to respond to mouse, keyboard, timer and other events allows DoodlePad to be used to develop a wide range of fun interactive graphics programs that are limited only by your imagination.

Connecting Events and Methods with Method References

The simplest way to invoke a method in response to an event is to connect the event associated with a given object to one of your methods. The most important prerequisite for making this connection is to ensure that your event handler method's signature matches what the event expects (by implementing the ShapeMouseEventHandler interface). Let's say you want to invoke a method when the user clicks on a Shape object of some kind. All mouse events, including the click event, requires that the method to be connected have the following four parameters in the given order:

#TypeDescription
1.ShapeThe Shape object that initiated the mouse event
2.doubleThe x-coordinate at which the event occurred
3.doubleThe y-coordinate at which the event occurred
4.intA number identifying the mouse button used

For example, the following method may be invoked by a mouse event because it implements the necessary four parameter types in the specified order.

public void onPressed(Shape shp, double, x, double y, int button) {
    System.out.println("The mouse was pressed at coordinates (" + x + "," + y + ")");
}

Every Shape object in DoodlePad inherits a set of methods used to attach mouse events to a suitable method - one method for each mouse event type. Each Shape method takes a single argument: a reference to the method to be invoked when the event occurs. Method references were added to Java in version 8, which is why Java 8 is the minimum required by DoodlePad. Method references are constructed using the :: binary operator. On the left side of the operator is the name of a class or object that implements a method, and on the right side of the operator is the method to reference.

As an example, let's say your class implements the previous onPress method, and you would like to invoke this method when the mouse is pressed on an Oval Shape object, a reference to which was saved as an instance variable named myOval. The following statement establishes this connection, so that when the mouse is pressed on myOval the onPress method implemented by this will be invoked.

myOval.setMousePressedHandler( this::onPress );

The inherited setMousePressedHandler(...) method is what is used to establish the connection for mouse-pressed events.

Following is a complete program demonstrating event handing in DoodlePad using method references.

import doodlepad.*;

public class PushButton {
    private RoundRect shpButton;    // Button Shape
    private boolean isOn;           // Button state

    public PushButton() {
        // Create button shape and initialize
        shpButton = new RoundRect(100, 100, 75, 50, 20, 20);
        shpButton.setFillColor(200);

        // Starts off
        isOn = false;

        // Set button click event handler method
        shpButton.setMousePressedHandler( this::onPressed );
    }

    private void onPressed(Shape shp, double x, double y, int button) {
        // Toggle button state
        isOn = !isOn;

        // Set button fill color based on state
        if (isOn) {
            shpButton.setFillColor(0, 255, 0);
        } else {
            shpButton.setFillColor(200);
        }
    }

    public static void main(String[] args) {
        // Create a new PushButton
        PushButton myPushButton = new PushButton();
    }
}

In this example we implement a simple graphical toggle button class named PushButton. For the button graphic we use a RoundRect Shape object. The PushButton constructor creates the RoundRect object and initializes its fill colors to gray. The PushButton class tracks its state using an isOn boolean instance variable. The class is initialized with isOn = false implying the button is initially off. The constructor also uses the setMousePressedHandler method to indicate that the object's onPressed method should be invoked when the RoundRect shape is pressed with the mouse. The onPressed method toggles the value of isOn and then resets the RoundRect fill color based on the current PushButton state. When the RoundRect is pressed with the mouse, the PushButton object state is toggled and the RoundRect fill color changes to green, indicating that the button was pressed. A second press toggles PushButton off and sets the RoundRect fill color back to gray.

The image on the right shows the output from running this example program and pressing the RoundRect Shape once with the mouse.

Shape Mouse Event-Related Methods

A wide variety of mouse events may be handled in a similar manner. Following is a list of all methods used to connect a mouse event with a Shape. Each method is used to associate a particular mouse event with a custom method. Each of the following methods takes a method reference as its only parameter. Each method reference must identify a method with a signature that matches the previously listed four parameter types in the given order, otherwise the compiler will complain.

MethodDescription
public void setMouseClickedHandler(ShapeMouseEventHandler handler) Set a method to be invoked when the mouse is clicked on a Shape. A mouse-click event occurs when the mouse is pressed and released at the same location.
public void setMouseDoubleClickedHandler(ShapeMouseEventHandler handler) Set a method to be invoked when the mouse is double-clicked on a Shape. A mouse-double-clicked event occurs when the mouse is pressed and released at the same location twice in succession.
public void setMousePressedHandler(ShapeMouseEventHandler handler) Set a method to be invoked when the mouse is pressed on a Shape. A mouse-pressed event occurs when the mouse button is pressed while over a Shape.
public void setMouseReleasedHandler(ShapeMouseEventHandler handler) Set a method to be invoked when the mouse is released on a Shape. A mouse-released event occurs when the mouse button is released while over a Shape.
public void setMouseMovedHandler(ShapeMouseEventHandler handler) Set a method to be invoked when a mouse is moved on a Shape. A mouse-moved event occurs when the mouse is moved over a Shape while the mouse button is not pressed.
public void setMouseDraggedHandler(ShapeMouseEventHandler handler) Set a method to be invoked when the mouse is dragged on a Shape. A mouse-dragged event occurs when the mouse is moved over a Shape while the mouse button is pressed.
public void setMouseEnteredHandler(ShapeMouseEventHandler handler) Set a method to be invoked when the mouse enters a Shape. A mouse-entered event occurs when the mouse is moved from a location outside the bounds of a Shape to a location within the bounds of a Shape.
public void setMouseExitedHandler(ShapeMouseEventHandler handler) Set a method to be invoked when the mouse exits a Shape. A mouse-exited event occurs when the mouse is moved from a location within the bounds of a Shape to a location outside the bounds of a Shape.

Handling Events by Overriding Base Class Methods

Another way to associate Shape events with custom methods is to subclass Shape and override the appropriate base class method with an implementation to be invoked when the event fires. The Shape base class implements a series of placeholder methods that do nothing, but exist purely to be overridden by a subclass when custom behavior is desired. This represents an alternative to the method reference approach for setting up custom event handlers, and may be used when comfortable with the concept of inheritance.

The Shape implements a series of "on" methods: one for each mouse event. For example, Shape implements a method named onMousePressed which is invoked when a Shape is clicked with the mouse. The signature of this method as well as all other methods that correspond with mouse events share a common signature with the types: double, double and int. These are the mouse event x and y coordinates and an integer identifying the mouse button in use. These parameters are identical to the signature of methods used in the method reference approach, minus the first parameter identifying the Shape object.

The following example illustrates an alternate way to implement the previous PushButton class. In this case the PushButton class extends the RoundRect Shape class. the mousePressed event is handled by overriding the onMousePressed() method. The remaining logic for this class is identical to the previous example.

import doodlepad.*;

public class PushButton extends RoundRect {
    private boolean isOn;   // Button state

    public PushButton(double x, double y, double w, double h) {
        super(x, y, w, h, 20, 20);

        // Initialize the button
        this.setFillColor(200);

        // Starts off
        isOn = false;
    }

    @Override
    public void onMousePressed(double x, double y, int button) {
        // Toggle button state
        isOn = !isOn;

        // Set button fill color based on state
        if (isOn) {
            this.setFillColor(0, 255, 0);
        } else {
            this.setFillColor(200);
        }
    }

    public static void main(String[] args) {
        // Create a new PushButton
        PushButton myPushButton = new PushButton(100, 100, 75, 50);
    }
}
        

Overridable Shape Event Methods

As mentioned, the Shape class implements one overridable method for each mouse event. The following table lists all methods that may be overridden in order to handle a triggered mouse event.

MethodDescription
public void onMouseClicked(double x, double y, int button) Override to handle a mouse-click event
public void onMouseDoubleClicked(double x, double y, int button) Override to handle a mouse-double-click event.
public void onMousePressed(double x, double y, int button) Override to handle a mouse-pressed event - when a mouse button is depressed.
public void onMouseReleased(double x, double y, int button) Override to handle a mouse-released event - when a mouse button is released after being depressed.
public void onMouseMoved(double x, double y, int button) Override to handle a mouse-moved event. This occurs when the mouse is moved over a Shape while no buttons are depressed.
public void onMouseDragged(double x, double y, int button) Override to handle a mouse-dragged event. This occurs when the mouse is moved over a Shape while simultaneously holding a mouse button down.
public void onMouseEntered(double x, double y, int button) Override to handle a mouse-entered event. This occurs when the mouse moves over a Shape from another Shape or the Pad.
public void onMouseExited(double x, double y, int button) Override to handle a mouse-exited event. This occurs when the mouse moves off a Shape on to another Shape or the Pad.

Other Event-Related Shape Methods

Shapes triggers one additional event beyond the above list of mouse events. The selectionChanged event is triggered whenever the selection status of a Shape changes. For example, if the user clicks on a selectable Shape that is not already selected, the Shape becomes selected, which is indicated by a light gray rectangle drawn around the Shape. If a suitable event handler method is attached to the Shape's selectionChange event, then as the Shape becomes selected, the event method will be invoked, indicating the Shape object whose selection state changed as well as if the Shape is currently selected. Likewise, if another Shape is clicked causing the currently selected Shape to be unselected, the event handler method will once again be invoked.

Both the method reference and overriding methods of handling triggered selectionChanged events are supported. Event handler methods to be attached to the selectionChanged event trigger using the method reference approach must have a signature with two parameters: Shape and boolean. This implements the ShapeSelectionEventHandler interface. The first parameter indicates the Shape object whose selection changed, and the second parameter indicates if that Shape is currently selected (true) or not (false).

The following two methods are used for handling triggered selectionChanged events. The first method attaches an event handler using the method reference approach. Override the second method to handle the triggered event using the method overriding approach.

MethodDescription
public void setSelectionChangedHandler(ShapeSelectionEventHandler handler) Specify a suitable method to handle selectionChanged events triggered by a Shape object. The method reference must implement the signature defined by the ShapeSelectionEventHandler interface.
public void onSelectionChanged(boolean selected) Override this method in a Shape subclass to handle selectionChanged events by overriding the base class method.

Pad Keyboard Event-Related Methods

MethodDescription
public void setKeyPressedHandler(Pad.PadKeyEventHandler handler)Assign an onKeyPressed event handler using a method reference.
public void setKeyReleasedHandler(Pad.PadKeyEventHandler handler)Assign an onKeyReleased event handler using a method reference.
public void setKeyTypedHandler(Pad.PadKeyTypedEventHandler handler)Assign an onKeyTyped event handler using a method reference.
public void onKeyPressed(java.lang.String keyText, java.lang.String keyModifiers)A method that can be overridden to handle key pressed events
public void onKeyReleased(java.lang.String keyText, java.lang.String keyModifiers)A method that can be overridden to handle key released events
public void onKeyTyped(char keyChar)A method that can be overridden to handle key typed events
public void addKeyListener(PadKeyListener o)Add object to the list of items that are notified on Pad's key events.
public void removeKeyListener(PadKeyListener o)Remove object from Pad's key listener list.

Pad Timer Event-Related Methods

MethodDescription
public void setTickHandler(Pad.PadTimerEventHandler handler)Assign an onTick event handler using a method reference.
public void onTick(long when)A method that can be overridden to handle the Pad timer`s tick event. The timer tick rate is set with the setTickRate() method. The timer is started by invoking the startTimer() method. The timer is stopped by invoking the stopTimer() method.
public void addTickListener(PadTickListener o)Add object to the list if items that are notified on Pad's timer tick action.
public void removeTickListener(PadTickListener o)Remove object from Pad's timer tick action listener list.

Pad Socket Event-Related Methods

MethodDescription
public void onClientOpened(int id)Invoked when a new client connection opens
public void onClientOpened(int id)Invoked when a new client connection opens
public void onClientReceived(int id, java.lang.String msg)Invoked when a connected client socket receives a message
public void onClientClosed(int id)Invoked when a client connection is closed
public void onClientError(int id, java.lang.String msg)Invoked when a connected client socket has has error
public void onClientInfo(int id, java.lang.String msg)Invoked when a connected client socket has some information to share
public void onServerStarted()Invoked when the listening server starts
public void onServerStopped()Invoked when the listening server stops and all connections are closed
public void onServerError(java.lang.String msg)Invoked when the listening server has an error
public void onServerInfo(java.lang.String msg)Invoked when the listening server has some information to share

Pad Mouse Event-Related Methods

MethodDescription
public void setMousePressedHandler(PadMouseEventHandler handler) Assign an onMousePressed event handler using a method reference.
public void setMouseReleasedHandler(PadMouseEventHandler handler) Assign an onMouseReleased event handler using a method reference.
public void setMouseMovedHandler(PadMouseEventHandler handler) Assign an onMouseMoved event handler using a method reference.
public void setMouseClickedHandler(PadMouseEventHandler handler) Assign an onMouseClicked event handler using a method reference.
public void setMouseDoubleClickedHandler(PadMouseEventHandler handler) Assign an onMouseDoubleClicked event handler using a method reference.
public void setMouseDraggedHandler(PadMouseEventHandler handler) Assign an onMouseDragged event handler using a method reference.
public void setMouseEnteredHandler(PadMouseEventHandler handler) Assign an onMouseEntered event handler using a method reference.
public void setMouseExitedHandler(PadMouseEventHandler handler) Assign an onMouseExited event handler using a method reference.
public void onMousePressed(double x, double y, int button) A method that can be overridden to handle mouse pressed events.
public void onMouseReleased(double x, double y, int button) A method that can be overridden to handle mouse released events.
public void onMouseMoved(double x, double y, int button) A method that can be overridden to handle mouse moved events.
public void onMouseClicked(double x, double y, int button) A method that can be overridden to handle mouse clicked events.
public void onMouseDoubleClicked(double x, double y, int button) A method that can be overridden to handle mouse double-clicked events.
public void onMouseDragged(double x, double y, int button) A method that can be overridden to handle mouse dragged events. A mouse dragged event is the same as a mouse moved event while the mouse is pressed.
public void onMouseEntered(double x, double y, int button) A method that can be overridden to handle mouse entered events.
public void onMouseExited(double x, double y, int button) A method that can be overridden to handle mouse exited events.
public void addMouseListener(PadMouseListener o) Add object to the list of items that are notified on Pad's mouse events.
public void removeMouseListener(PadMouseListener o) Remove object from Pad's mouse listener list.