The Item
interface provides access to a set of named
properties. Each property is identified by a property
identifier (PID) and a reference to such a property can be queried
from an Item
with
getItemProperty()
using the identifier.
Examples on the use of items include rows in a Table
,
with the properties corresponding to table columns, nodes in a
Tree
, and the the data bound to a
Form
, with item's properties bound to individual form
fields.
Items are generally equivalent to objects in the object-oriented model, but
with the exception that they are configurable and provide an event handling
mechanism. The simplest way to utilize Item
interface
is to use existing implementations. Provided utility classes include a
configurable property set (PropertysetItem
) and a
bean-to-item adapter (BeanItem
). Also, a
Form
implements the interface and can therefore be used
directly as an item.
In addition to being used indirectly by many user interface components, items
provide the basic data model underlying the Form
component. In simple cases, forms can even be generated automatically from
items. The properties of the item correspond to the fields of the form.
The Item
interface defines inner interfaces for
maintaining the item property set and listening changes made to
it. PropertySetChangeEvent
events can be emitted by a
class implementing the PropertySetChangeNotifier
interface. They can be received through the
PropertySetChangeListener
interface.
The PropertysetItem
is a generic implementation of
the Item
interface that allows storing
properties. The properties are added with
addItemProperty()
, which takes a name and the
property as parameters.
The following example demonstrates a typical case of collecting
ObjectProperty
properties in an item:
PropertysetItem item = new PropertysetItem(); item.addItemProperty("name", new ObjectProperty("Zaphod")); item.addItemProperty("age", new ObjectProperty(42)); // Bind it to a component Form form = new Form(); form.setItemDataSource(item);
The BeanItem
implementation of the
Item
interface is a wrapper for Java Bean
objects. In fact, only the setters and getters are required while
serialization and other bean features are not, so you can wrap almost any
POJOs with minimal requirements.
// Here is a bean (or more exactly a POJO) class Person { String name; int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age.intValue(); } } // Create an instance of the bean Person bean = new Person(); // Wrap it in a BeanItem BeanItem<Person> item = new BeanItem<Person>(bean); // Bind it to a component Form form = new Form(); form.setItemDataSource(item);
You can use the getBean()
method to get a
reference to the underlying bean.
You may often have composite classes where one class "has a" another
class. For example, consider the following
Planet
class which "has a" discoverer:
// Here is a bean with two nested beans public class Planet implements Serializable { String name; Person discoverer; public Planet(String name, Person discoverer) { this.name = name; this.discoverer = discoverer; } ... getters and setters ... } ... // Create an instance of the bean Planet planet = new Planet("Uranus", new Person("William Herschel", 1738));
When shown in a Form
, for example, you would
want to list the properties of the nested bean along the properties of
the composite bean. You can do that by binding the properties of the
nested bean individually with a MethodProperty
or NestedMethodProperty
. You should usually
hide the nested bean from binding as a property by listing only the
bound properties in the constructor.
// Wrap it in a BeanItem and hide the nested bean property BeanItem<Planet> item = new BeanItem<Planet>(planet, new String[]{"name"}); // Bind the nested properties. // Use NestedMethodProperty to bind using dot notation. item.addItemProperty("discoverername", new NestedMethodProperty(planet, "discoverer.name")); // The other way is to use regular MethodProperty. item.addItemProperty("discovererborn", new MethodProperty<Person>(planet.getDiscoverer(), "born"));
The difference is that NestedMethodProperty
does not access the nested bean immediately but only when accessing
the property values, while when using
MethodProperty
the nested bean is accessed when
creating the method property. The difference is only significant if
the nested bean can be null or be changed later.
You can use such a bean item for example in a
Form
as follows:
// Bind it to a component Form form = new Form(); form.setItemDataSource(item); // Nicer captions form.getField("discoverername").setCaption("Discoverer"); form.getField("discovererborn").setCaption("Born");
The BeanContainer
and
BeanItemContainer
allow easy definition of
nested bean properties with
addNestedContainerProperty()
, as described in
the section called “Nested Properties”.