Algo comum em programação Swing é ter métodos para atualizar objetos e a view como o seguinte.

public void atualizarObjeto(Pessoa x){
x.setNome(nomeField.getText());
x.setCpf(cpfField.getText());
x.setIdade(Integer.parseInt(idadeField.getText()));
}

public void atualizarObjeto(Pessoa x){
nomeField.setText(x.getNome());
cpfField.setText(x.getCpf());
idadeField.setText(x.getIdade());
}

Nesse exemplo temos apenas 3 atributos mas ao adicionar mais um vemos a necessidade de colocar mais uma linha em cada um desses métodos. Com o tempo esse processo começa a ficar no minimo chato.
Pensando nisso criei a classe Binder.

PS: Para usar precisa baixar os fontes ou o jar na pagina Towel Project.

Considere para o exemplo a seguinte classe:

public class Person {
	private String name;
	private int age;
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public Person getParent() {
		return parent;
	}

	public void setParent(Person parent) {
		this.parent = parent;
	}
}

E um IntFormatter:

public class IntFormatter implements Formatter {
	@Override
	public String format(Object obj) {
		return Integer.toString((Integer) obj);
	}
	@Override
	public String getName() {
		return "int";
	}
	@Override
	public Object parse(String s) {
		return Integer.parseInt(s);
	}
}

“[name:nomeDoAtributo] [fmt:formatter][pfx:prefixo][dflt:valorDefault]”

Onde.
nomeDoAtributo: nome do atributo na classe.
formatter (Opcional): deve ser igual ao retornado pelo método getName do Formatter.
prefixo (Opcional): quando precisamos na mesma tela ter mais de um Binder(Para dois tipos de objetos diferentes). Esse nome deve ser passado no construtor do Binder.
valorDefault (Opcional): no caso em que o valor no objeto for null ou vazio esse valor é assumido para a view.

Todos os parametros são colocados no name dos JComponents.

Exemplo funcional.


import com.towel.bind.Binder;

public class BinderTest extends JFrame {
	private JTextField nomeField, idadeField;
	private JButton button;
	private Binder binder;

	public BinderTest() {
		super("Binder");
		nomeField = new JTextField(10);
		idadeField = new JTextField(10);
		button = new JButton("Run");

		JPanel content = new JPanel(new FlowLayout());
		content.add(new JLabel("Nome:"));
		content.add(nomeField);
		content.add(new JLabel("Idade:"));
		content.add(idadeField);
		content.add(button);

		nomeField.setName("[name:name]");
		idadeField.setName("[name:age][fmt:int]");

		setContentPane(content);

		binder = new Binder(this, Person.class, new IntFormatter());

		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				Person person = new Person();
				try {
					binder.updateModel(person);
				} catch (Exception e) {
					// Um formatter pode lançar uma RuntimeException.
				}
				System.out.println(person.getName());
				System.out.println(person.getAge());

				Person newOne = new Person();
				binder.updateView(newOne);
			}
		});

		pack();
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}

	public static void main(String[] args) {
		new BinderTest();
	}
}

Ao clicar no botão podemos ver o que digitamos no console pois após binder.updateModel temos os valores no objeto.
Após isso os campos ficam limpos pois é chamado binder.updateView com um novo Person e esses campos ainda estão vazios.

O construtor com pfx seria como o seguinte.

binder = new Binder("prefixoUsado", this, Person.class, new IntFormatter());

Mas teriamos que colocar esse atributo em cada componente que queiramos.

Binder usa um método recursivo para pegar os componentes, então não se preocupe em alinhar seus componentes em varios JPanels.ributo