Let us put into practice what we learned of event handling in Section 3.5, “Events and Listeners”. You can handle events in three basic ways, as shown below.

The following example follows a typical pattern where you have a Button component and a listener that handles user interaction (clicks) communicated to the application as events. Here we define a class that listens click events.

public class TheButton implements Button.ClickListener {
    Button thebutton;

    /** Creates button into given container. */
    public TheButton(AbstractComponentContainer container) {
        thebutton = new Button ("Do not push this button");
        thebutton.addListener(this);
        container.addComponent(thebutton);
    }
    
    /** Handle button click events from the button. */
    public void buttonClick (Button.ClickEvent event) {
        thebutton.setCaption ("Do not push this button again");
    }
}

As an application often receives events for several components of the same class, such as multiple buttons, it has to be able to distinguish between the individual components. There are several techniques to do this, but probably the easiest is to use the property of the received event, which is set to the object sending the event. This requires keeping at hand a reference to every object that emits events.

public class TheButtons implements Button.ClickListener {
    Button thebutton;
    Button secondbutton;

    /** Creates two buttons in given container. */
    public TheButtons(AbstractComponentContainer container) {
        thebutton = new Button ("Do not push this button");
        thebutton.addListener(this);
        container.addComponent(thebutton);
        
        secondbutton = new Button ("I am a button too");
        secondbutton.addListener(this);
        container.addComponent (secondbutton);
    }
    
    /** Handle button click events from the two buttons. */
    public void buttonClick (Button.ClickEvent event) {
        if (event.getButton() == thebutton)
            thebutton.setCaption("Do not push this button again");
        else if (event.getButton() == secondbutton)
            secondbutton.setCaption("I am not a number");
    }
}

Another solution to handling multiple events of the same class involves attaching an event source to a listener method instead of the class. An event can be attached to a method using another version of the addListener() method, which takes the event handler method as a parameter. The method can be passed either by the name of the method or as a Method object. In the example below, we use the name of the method, as a string (which is not checked at compile time).

public class TheButtons2 {
    Button thebutton;
    Button secondbutton;

    /** Creates two buttons in given container. */
    public TheButtons2(AbstractComponentContainer container) {
        thebutton = new Button ("Do not push this button");
        thebutton.addListener(Button.ClickEvent.class, this,
                              "theButtonClick");
        container.addComponent(thebutton);
        
        secondbutton = new Button ("I am a button too");
        secondbutton.addListener(Button.ClickEvent.class, this,
                                 "secondButtonClick");
        container.addComponent (secondbutton);
    }
    
    public void theButtonClick (Button.ClickEvent event) {
        thebutton.setCaption ("Do not push this button again");
    }

    public void secondButtonClick (Button.ClickEvent event) {
        secondbutton.setCaption ("I am not a number!");
    }
}

Adding a listener method with addListener() is really just a wrapper that creates a com.vaadin.event.ListenerMethod listener object, which is an adapter from a listener class to a method. It implements the java.util.EventListener interface and can therefore work for any event source using the interface. Notice that not all listener classes necessarily inherit the EventListener interface.

The third way, which uses anonymous local class definitions, is often the easiest as it does not require cumbering the managing class with new interfaces or methods. The following example defines an anonymous class that inherits the Button.ClickListener interface and implements the buttonClick() method.

public class TheButtons3 {
    Button thebutton;
    Button secondbutton;

    /** Creates two buttons in given container. */
    public TheButtons3(AbstractComponentContainer container) {
        thebutton = new Button ("Do not push this button");

        /* Define a listener in an anonymous class. */
        thebutton.addListener(new Button.ClickListener() {
            /* Handle the click. */
            public void buttonClick(ClickEvent event) {
                thebutton.setCaption (
                        "Do not push this button again");
            }
        });
        container.addComponent(thebutton);
        
        secondbutton = new Button ("I am a button too");
        secondbutton.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                secondbutton.setCaption ("I am not a number!");            
            }
        });
        container.addComponent (secondbutton);
    }
}

Other techniques for separating between different sources also exist. They include using object properties, names, or captions to separate between them. Using captions or any other visible text is generally discouraged, as it may create problems for internationalization. Using other symbolic strings can also be dangerous, because the syntax of such strings is checked only runtime.

Events are usually emitted by the framework, but applications may need to emit them too in some situations, such as when updating some part of the UI is required. Events can be emitted using the fireEvent(Component.Event) method of AbstractComponent. The event is then relayed to all the listeners of the particular event class for the object. Some components have a default event type, for example, a Button has a nested Button.ClickEvent class and a corresponding Button.ClickListener interface. These events can be triggered with fireComponentEvent().