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:
<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
.
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:
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:
package foo;
...
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 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