Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Swing

Beans Binding with Human Face

0.00/5 (No votes)
21 Apr 2011CPOL2 min read 18.1K  
Shows how to use beans binding with swinghtmltemplate

Introduction

In my previous article, I showed how to easily compose swing forms with HTML markup. Since that time, my swinghtmltemplate library moved to version 0.3 with beans binding support. Here, I'll show basic examples of using binding.

Background

Binding is the process of synchronizing the value of two properties. Concerning swing, this allows, for example, to keep in sync the «text» property of JTextField with «name» property of Person. You can read more on binding here.

Using the Code

Add the library using maven:

XML
<dependencies> 
   <dependency> 
      <groupId>com.googlecode.swinghtmltemplate</groupId>
      <artifactId>swinghtmltemplate</artifactId>
      <version>0.3</version>
   </dependency>
</dependencies>
<repositories>
   <repository>
      <id>swinghtmltemplate</id>
      <name>Swing html template repo</name>
      <url>http://swinghtmltemplate.googlecode.com/svn/maven-repository</url>
      <releases>
         <enabled>true</enabled>
         <updatePolicy>never</updatePolicy>
      </releases>
      <snapshots>
         <enabled>false</enabled>
      </snapshots>
   </repository>
</repositories>

You can also download distributive with dependencies.

Let's create domain object — person. It has two properties: name and email.

Java
public class Person {
   private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
   private String name;
   private String email;
 
   public String getName() {
      return name;
   }
 
   public void setName(String name) {
      Object old = this.name;
      this.name = name;
      pcs.firePropertyChange("name", old, name);
   } 

   public String getEmail() {
      return email;
   } 

   public void setEmail(String email) {
      Object old = this.email;
      this.email = email;
      pcs.firePropertyChange("email", old, email);
   } 

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

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

We want to make a form with 2 input fields and bind them to name and email properties.

To specify binding, you must do 2 things:

  • Provide dom model with model values
  • Specify binding for component

The first task can be done with:

Java
DomModel domModel = ...;
model.addModelElement("person", new Person());

Now the person object is passed to the dom model under the «person» key, so you can use it with ${person}.

If you have controller for your form, you can provide model values with @ModelAttribute annotation.

Let's create a controller for our form:

Java
package foo;
 
...//imports
 
public class PersonForm extends JPanel {
   private DomModel model;
   
   @ModelElement("person")
   private Person person = new Person();    

   public PersonForm() {
      try {
         model = Binder.bind(this, true);
      }
      catch (JDOMException e) {
         e.printStackTrace();
      }
      catch (IOException e) {
         e.printStackTrace();
      }
   } 

   public Person getPerson () {
      return person;
   } 

   public void setPerson (Person person) {
      Object old = this.person ;
      this.person = person;
      firePropertyChange("person", old, person);
   } 

   public void onOK() {
      System.out.println(person.getName()+" "+person.getEmail());
   } 

   public static void main(String[] args) throws JDOMException, IOException {
      PersonForm personForm = new PersonForm();

      Person person = new Person();
      person.setName("John Doe");
      personForm.setPerson(person);

      JFrame f = new JFrame("Test");
      f.setSize(400, 200); 
      f.getContentPane().add(personForm);
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setVisible(true);
   } 
} 

You can see that we pass our domain object to the dom model under the «person» name. Model is filled when Binder.bind(this, true); is invoked, so you can prepare domain values before this call.

Also notice that we are firing a property change in setter. This is the usual Java bean routine.

In the main method, we create an instance of our controller, place it in JFrame. We also create an initial person with the specified name.

Next let's create a form and see how to bind it to person:

HTML
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://www.oracle.com/swing">
<head>
</head>
<body style="display: border;width: 400; height:300; border: empty 12 12 12 12">
<form>
   <label for="name">Name:</label>
   <input id='name' type="text" value="${person.name}" align="wrap"/>
   <label for="email">Email:</label>
   <input id="email" type="text" value="${person.email}" align="wrap" />
   <input type='button' onclick="onOK" text="OK"/>
</form> 
</body>
</html>

We place this code in «/src/foo/PersonForm.html».

Look at the input tags. We specify binding in the «value» attribute. First input is binded to the person's "name" property, second — to the "email" property. The binding is bidirectional, so changing text in the input fields will update person, and changing person's properties will update text fields.

We added a button to the panel — the last input. It has attribute 'onclick' with the value «onOK». This means that the «PersonForm.onOK()» will be invoked when clicking on the button.

You can try the example, enter some text, press button and see that the person's properties are changed.

Links

History

  • 21st April, 2011: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)