Update: the APIs shown in this blog entry have changed slightly in newer releases of Metawidget. Specifically .setBindingClass has been replaced by .addWidgetProcessor. Please download the latest documentation from http://metawidget.orgThis is a short tutorial on using Beans Binding in
Metawidget. It should take around 10 minutes.
I'd recommend you use your preferred Java development environment. If you use an Integrated Development Environment (IDE), you'll need to start a new Java project and add
metawidget.jar to it. Otherwise, you just need to ensure
metawidget.jar is on your classpath.
The ObjectFirst, we need an object to map from. Create a
Person class under a package
com.myapp:
package com.myapp;
public class Person {
private String fullname = "Homer Simpson";
private int kids = 3;
private boolean retired = false;
public String getFullname() {
return this.fullname;
}
public void setFullname( String fullname ) {
this.fullname = fullname;
}
public int getKids() {
return this.kids;
}
public void setKids( int kids ) {
this.kids = kids;
}
public boolean isRetired() {
return this.retired;
}
public void setRetired( boolean retired ) {
this.retired = retired;
}
public String toString() {
String toReturn = "Fullname: " + this.fullname + "\n";
toReturn += "Kids: " + this.kids + "\n";
toReturn += "Retired: " + this.retired + "\n";
return toReturn;
}
}
The InterfaceNext, we need a Swing app:
package com.myapp;
import javax.swing.JFrame;
import org.metawidget.inspector.javabean.JavaBeanInspector;
import org.metawidget.swing.SwingMetawidget;
public class Main {
public static void main( String[] p_args ) {
final Person person = new Person();
final SwingMetawidget mw = new SwingMetawidget();
mw.setInspector( new JavaBeanInspector() );
mw.setToInspect( person );
final JFrame frame = new JFrame( "Beans Binding in Metawidget" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( mw );
frame.setSize( 400, 150 );
frame.setVisible( true );
}
}
The OutputRun the code. You will see the screen below:
The
SwingMetawidget has automatically populated itself with child components at runtime. It has chosen
JTextField,
JSpinner, and
JCheckBox components to suit the fields of the Person class.
Metawidget is all about being
native to the existing platform: it doesn't impose any additional dependencies on your code.
By default, Swing doesn't provide an Object-to-JComponent mapping mechanism, so Metawidget doesn't either. If you have Beans Binding available, however, Metawidget will use it.
Turn on Beans BindingAdd
beansbinding-1.2.1.jar to your classpath, and the following line to the
Main class (highlighted in bold):
package com.myapp;
import javax.swing.JFrame;
import org.metawidget.inspector.javabean.JavaBeanInspector;
import org.metawidget.swing.SwingMetawidget;
import org.metawidget.swing.binding.beansbinding.BeansBinding;
public class Main {
public static void main( String[] p_args ) {
final Person person = new Person();
final SwingMetawidget mw = new SwingMetawidget();
mw.setInspector( new JavaBeanInspector() );
mw.setBindingClass( BeansBinding.class );
mw.setToInspect( person );
final JFrame frame = new JFrame( "Beans Binding in Metawidget" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( metawidget );
frame.setSize( 400, 150 );
frame.setVisible( true );
}
}
Run the code again. You will see the same screen, but this time the
JComponents are automatically populated by Beans Binding:
Populate the Values BackTo have Metawidget populate the values back, add the following code to the
Main class (highlighted in bold):
package com.myapp;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.metawidget.inspector.javabean.JavaBeanInspector;
import org.metawidget.swing.SwingMetawidget;
import org.metawidget.swing.binding.beansbinding.BeansBinding;
public class Main {
public static void main( String[] p_args ) {
final Person person = new Person();
final SwingMetawidget mw = new SwingMetawidget();
mw.setInspector( new JavaBeanInspector() );
mw.setBindingClass( BeansBinding.class );
mw.setToInspect( person );
final JFrame frame = new JFrame( "Beans Binding in Metawidget" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( mw );
frame.getContentPane().add(
new JButton( new AbstractAction( "Save" ) {
public void actionPerformed( ActionEvent e ) {
mw.save();
JOptionPane.showMessageDialog( frame, person.toString() );
}
} ), BorderLayout.SOUTH );
frame.setSize( 400, 150 );
frame.setVisible( true );
}
}
Run the code again. This time, change some of the values and click the
Save button. Metawidget will populate the values back, and display the resulting
toString of the
Person class:
Fine-Tune Component CreationMetawidget supports several ways to control the components it creates. Here, we use the 'child components' approach: if you add a child
JComponent with the same name as Metawidget would normally have given its automatically created component, Metawidget will use it in preference - but it will still apply Beans Binding for you.
Add the following code to the
Main class (highlighted in bold):
package com.myapp;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.metawidget.inspector.javabean.JavaBeanInspector;
import org.metawidget.swing.SwingMetawidget;
import org.metawidget.swing.binding.beansbinding.BeansBinding;
public class Main {
public static void main( String[] p_args ) {
final Person person = new Person();
final SwingMetawidget mw = new SwingMetawidget();
mw.setInspector( new JavaBeanInspector() );
mw.setBindingClass( BeansBinding.class );
mw.setToInspect( person );
JComboBox combo = new JComboBox(
new Object[]{ null, 1, 2, 3, 4 } );
combo.setName( "kids" );
mw.add( combo );
final JFrame frame = new JFrame( "Beans Binding in Metawidget" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( mw );
frame.getContentPane().add(
new JButton( new AbstractAction( "Save" ) {
public void actionPerformed( ActionEvent e ) {
mw.save();
JOptionPane.showMessageDialog( frame, person.toString() );
}
} ), BorderLayout.SOUTH );
frame.setSize( 400, 150 );
frame.setVisible( true );
}
}
Run the code. The
JComboBox will take the place of the
JSpinner, but it will still be initialized by Beans Binding and data will still be saved back when clicking the
Save button.
ConclusionThat concludes our simple Beans Binding example. For a more 'real world' example (including using Beans Binding converters), please see the
Address Book example in the Metawidget distribution.