Listeners and events

How do listeners and events work in general? I tried to receive events from tree but no luck and only example you have is Calc.java!

Here’s an demo of harddisk file explorer that registers “this” class as an listener for Tree component, it then receives all events for the respective component and demonstrates value change event (feel free to experiment and add other events too)


package com.itmill.toolkit.example;

import java.io.File;

import com.itmill.toolkit.data.util.FilesystemContainer;
import com.itmill.toolkit.data.util.FilesystemContainer.FileItem;
import com.itmill.toolkit.ui.*;
import com.itmill.toolkit.ui.Component.Event;
import com.itmill.toolkit.ui.Component.Listener;

/**
 * Browsable file explorer using Toolkit Tree component. Demonstrates: how to
 * use <code>com.itmill.toolkit.ui.Component.Tree</code> datasource container,
 * how to create <code>com.itmill.toolkit.data.util.FilesystemContainer</code>,
 * how to read <code>com.itmill.toolkit.ui.Component.Event</code> objects, how
 * to receive and handle any event by implementing
 * <code>com.itmill.toolkit.ui.Component.Listener</code>.
 * 
 * @since 4.0.0
 * 
 */
public class TreeFilesystemContainer extends com.itmill.toolkit.Application
		implements Listener {

	// Default is root directory, e.g. / on unix or \ on windows
	private static final String DIR_ROOT = "" + File.separatorChar;

	// Filesystem explorer panel and it's components
	private Panel explorerPanel = new Panel("Filesystem explorer");

	private Tree filesystem = new Tree();

	// File properties panel and it's components
	private Panel propertyPanel = new Panel("File properties");

	private Label fileProperties = new Label();

	public void init() {
		Window main = new Window("Tree demo");
		setMainWindow(main);

		// set the application to use Corporate -theme
		setTheme("corporate");

		// Main window contains heading and two panels
		main.addComponent(new Label("<h3>Tree demo</h3>", Label.CONTENT_XHTML));
		main.addComponent(propertyPanel);
		main.addComponent(explorerPanel);

		// Explorer panel contains tree
		explorerPanel.addComponent(filesystem);

		// Property panel contains label
		propertyPanel.addComponent(fileProperties);
		fileProperties.setCaption("No file selected.");
		propertyPanel.setEnabled(false);

		// Populate tree with FilesystemContainer
		FilesystemContainer fsc = new FilesystemContainer(new File(DIR_ROOT),
				true);
		filesystem.setContainerDataSource(fsc);
		// "this" handles all filesystem events
		// e.g. node clicked, expanded etc.
		filesystem.addListener((Listener) this);
		// Value changes are immediate
		filesystem.setImmediate(true);
	}

	/**
	 * Listener for any component events. This class has been registered as an
	 * listener for component fsTree.
	 */
	public void componentEvent(Event event) {
		// Check if event occured at fsTree component
		if (event.getSource() == filesystem) {
			// Check if event is about changing value
			if (event.getClass() == Field.ValueChangeEvent.class) {
				// Update property panel contents
				FileItem fileItem = (FileItem) filesystem.getItem(filesystem
						.getValue());
				fileProperties.setIcon(fileItem.getIcon());
				fileProperties.setCaption(fileItem.getName() + ", size "
						+ fileItem.getSize() + " bytes.");
			}
			// here we could check for other type of events for filesystem
			// component
		}
		// here we could check for other component's events
	}

}

hello

i have a new question but is also about events and listeners

i am trying to add multiple listeners to different components such as CheckBoxes and Select.

I am suprised it does not work … the event is supposed to work in such a way like described below::

if a user checks box then a drop list should be added … and when user selects item from drop down lists it should listener to this event also

all of these items are in same layoutcomponent

any idea before i post my code…if this does not work??

thnx
newbabe

hey mwandu.

You can add listners to all components, they are all catched up by a valuechangelistner.

I hope I understood what you are doing correctly. I wrote this code but didn’t test it, so sorry if there are errors. This is a simple window with two components, one checkbox and one select, which are both listened for changes


package hello;

import com.itmill.toolkit.Application;
import com.itmill.toolkit.data.Property.ValueChangeEvent;
import com.itmill.toolkit.data.Property.ValueChangeListener;
import com.itmill.toolkit.ui.CheckBox;
import com.itmill.toolkit.ui.Select;
import com.itmill.toolkit.ui.Window;

public class MyView extends Application implements ValueChangeListener {
    CheckBox myCheckBox;
    Select mySelectField;

    @Override
    public void init() {
        // Set up the UI
        Window main = new Window("The Main Window");
        setMainWindow(main);
        // Add the checkbox and give it a listener
        myCheckBox = new CheckBox("my checkbox", false);
        myCheckBox.addListener(this);
        // Add the select field and give it a listener.
        mySelectField = new Select("my select");
        mySelectField.addListener(this);
        // Hide it from the UI
        mySelectField.setVisible(false);
        // Add both to the main UI
        main.addComponent(myCheckBox);
        main.addComponent(mySelectField);
    }
    public void valueChange(ValueChangeEvent event) {
        if (event.getProperty() == myCheckBox) {
            // view the select if the checkbox is activated
            if ((Boolean) myCheckBox.getValue() == true)
                mySelectField.setVisible(true);
            else
                mySelectField.setVisible(false);
        } else if (event.getProperty() == mySelectField) {
            //get the value from the select if the selects value has changed
            Object o = mySelectField.getValue();
            // do your stuff with the selection
        }
    }
}

I need to add event listeners to TextFields. I’ve noticed that this works:


myTextField.setImmediate(true);
myTextField.addListener(new Property.ValueChangeListener() {
	        public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
				doThings();
		}
	});

but this doesn’t:


public class myClass implements Property.ValueChangeListener {

.....

myTextField.setImmediate(true);
myTextField.addListener(this);

....

public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
		if (valueChangeEvent.getProperty().equals(myTextField)) {
                    doThings();
                }
}


This latter way works with Tables and Selects. Is there a way to make it work for TextFields too? If there are many textfields, it’s a bit inefficient to add a separate listener to each and every one.

Are you sure that the change events are originating from the textfields - not from their data-sources? Just put a breakpoint into the event-handler and see the result of getProperty()

If the property == textfield.getPropertyDataSource(), should we consider this to be a bug as you have selected to listen to textfield, not the property?

Are you sure your comparison in it if-clause is valid for your case?
The code included does not show how myTextField is created, and what potentially happens to in between. Is valueChange() called at all? Are you using FieldFactory or generated table columns or something like that?

(Also, I think it would be more appropriate to use == instead of equals(), but that’s not the issue here, since TextField effectively uses Object.equals()).

Regarding Joonas’ post: actually, I think changing the propertyDataSource should work as expected, unless it’s a Property that does not implement Property.ValueChangeNotifier…

Best Regards,
Marc