Documentation

Beans Binding (JSR 295)

JFormDesigner supports the Beans Binding specification (JSR 295).

A binding syncs two properties: the source property with the target property. The source is usually a (non-visual) data model object and the target is usually a UI component (e.g. a JTextField). Initially the value of the source property is copied to the target property. Depending on the "Update strategy", a binding tracks changes on both properties and syncs the properties.

Binding Source and Target

Beans Binding is open source and not part of the standard Java distribution. You must ship an additional library with your application. JFormDesigner includes beansbinding.jar, beansbinding-doc.zip and beansbinding-src.zip in its redistributables.

Maven Central Repository: groupId: org.jdesktop artifactId: beansbinding version: 1.2.1

API documentation: doc.formdev.com/beansbinding/
Source code: github.com/JFormDesigner/swing-beansbinding

The Bindings view 1 gives a good overview of all bindings in the form. The Show Bindings View button 2 makes this view visible. The Bindings property category 3 in the Properties view shows the bindings of the selected component and you can add (Add Binding), edit (Edit Binding) and remove (Remove Binding) bindings. Small arrows 4 indicate that the property is bound. Binding groups are also shown in the Structure view 5. The Binding palette category 6 provides useful components.

Binding Main Window

Add/Edit Bindings

There are several ways to add/edit bindings:

  • Right-click on a component in the Design or Structure view and select Bind from the popup menu. To edit an existing binding, select a bound property from the Bind submenu.
  • Click the Add/Edit Binding button (Add Binding/Edit Binding) in the Bindings property category in Properties view.
  • Right-click on a component property in the Properties view and select Bind from the popup menu.
  • Use the Add/Properties command in the Bindings view.

Remove Bindings

To remove existing bindings do one of:

  • Click the Remove Binding button (Remove Binding) in the Bindings property category in Properties view.
  • Use the Remove command in the Bindings view.

Binding Dialog

This dialog enables you to edit all options of one binding.

General tab

Binding (General)
Field Description
Source The source object.
Source path The path (or expression) that identifies the source property.
Detail path The path (or expression) that determines what is displayed to the user in the target JList.
(only if target is JList.elements)
Target The target object.
Target path The path (or expression) that identifies the target property.
Update strategy Specifies how the properties are kept synchronized. Possible values: "Always sync (read-write)", "Only read from source (read-only)" and "Read once from source (read-once)".
Update source when Specifies when the source is updated from the target. Possible values: "While typing", "On focus lost" and "On focus lost or Enter key pressed".
(only if target is JTextComponent.text)
Ignore adjusting If enabled, do not update properties until the user finished adjusting. E.g. while a slider is adjusting its value or while the list selection is being updated.
(only if target is JSlider.value, JList.selectedElement(s) or JTable.selectedElement(s))

Advanced tab

Binding (Advanced)
Field Description
Name The binding's name. Useful for BindingGroup.getBinding(name).
Group The group this binding belongs to.
Converter The Converter that converts the value from source type to target type and vice versa.
Validator The Validator that validates the value before passing it from the target back to the source property.
Source null Used if the value of the source property is null.
Source unreadable Used if the source property is unreadable.
Target null Used if the value of the target property is null.
Bind immediately Bind this binding immediately after creation. Otherwise, bind when the group is bound.

Table Binding tab

On this tab you can bind List<E> element properties to JTable columns. Each item in the source List<E> represents a row in the JTable. See JTableBinding for details about table binding.

This tab is enabled if source is an instance of java.util.List<E>, target an instance of javax.swing.JTable and target property is elements.

Binding (Table Binding)
Field Description
Editable Specifies whether the table cells are editable or not.
Columns The column bindings. The Source Path identifies the source property in <E>. The Column Name is shown in the JTable column header. Each column binding may have its own Converter, Validator and Alternative Values.

Path or Expression

To address source or target properties you can either use a path or an expression. Select the Expression Language button (Expression Language) left to the input field to enter an expression.

A path (implemented by BeanProperty) uses a dot-separated path syntax. E.g. task.title addresses the title property of an object's task property. This is equivalent to source.getTask().getTitle().

An expression (implemented by ELProperty) uses the Expression Language (EL) also known from JSP and JSF. Besides a dot-separated path syntax to address properties (e.g. "${task.title}") it also supports following operators:

  • Arithmetic: +, -, *, / and div, % and mod
  • Logical: and, &&, or, ||, not, !
  • Relational: ==, eq, !=, ne, <, lt, >, gt, <=, ge, >=, le
  • Empty: empty
  • Conditional: A ? B : C

EL expression examples:

EL expression Result
${task.title} The title property of an object's task property.
${firstName} ${lastName} Concatenation of firstName and lastName properties.
${mother.age > 65} true if mother is older than 65, false otherwise.
${image.width * image.height} Computes the number of pixels of an image.
${image.width * image.height * 4} Computes the number of bytes of an 32 bit image.

Following words are reserved for the EL and should not be used as identifiers:

  and   or    not   div   mod
  eq    ne    lt    gt    ge    le
  true  false null  empty instanceof

Data model

The data model used by Beans Binding (JSR 295) is based on the JavaBeans specification. Getters are necessary to read property values and setters to modify property values. On modifications, property change events should be fired so that beans binding can update the UI components. E.g.:

public class Task {
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        String oldTitle = this.title;
        this.title = title;
        changeSupport.firePropertyChange("title", oldTitle, title);
    }

    private final PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        changeSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        changeSupport.removePropertyChangeListener(listener);
    }
}

Data model access

The source and target combo boxes in the Binding dialog offer only the components added to the form. To bind your data model to form components, you could add an instance of your data object to the form (using Choose Bean), but this requires that the data object is a JavaBean with public null constructor, which is not always possible.

The preferred way to access the data model for binding is to add a getter for the data model to the form class. E.g.:

public class TaskViewForm extends JPanel {
    private Task task;

    public Task getTask() {
        return task;
    }
}

After compiling the form class, you can use this as binding source and task.someProperty as binding source path.

Add a setter to the form class, if the whole data model may change. E.g.:

public class TaskViewForm extends JPanel {
    public void setTask(Task task) {
        Task oldTask = this.task;
        this.task = task;
        firePropertyChange("task", oldTask, task);
    }
}

How to bind data to a JTable

Beans Binding requires that the data is in a java.util.List (or ObservableList). The type of each data row should be specified as type parameter to the list. E.g. java.util.List<MyData>. The data class should have getters and setters for its values, which can bound to table columns.

Steps to bind a table:

  1. Add a java.util.List component from the Bindings palette category to the form. JFormDesigner creates a variable for the list in the Java code, but does not assign a value to it. It is up to you, to assign data to the list before invoking initComponents().
  2. Set the Type Parameters property (expand the Class property in Properties view) of the List to your data class (e.g. MyData). Make sure that the data class is compiled and in the classpath of the project.
  3. Add a JTable to the form.
  4. Right-click on the table and select Bind > elements from the popup menu, which opens the Binding dialog.
  5. On the General tab, set the source to your List object and leave the source path empty.
  6. Switch to the Table Bindings tab.
  7. Click the Add Multiple button and add columns.

Examples

For examples that use Beans Binding, take a look at the package com.jformdesigner.examples.beansbinding in the examples.