Binder – Atualizando objetos facilmente.

29 07 2009

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

About these ads

Ações

Informação

11 respostas

10 07 2009
Aelxandre

Fala cara,

li o seu post e achei interessante.

mais oq ue você acha de gerar um masterBind quando criar o frame ou seja o masterbind seria na verdade a ‘tabela/view’ principal na sua form com isso gerar componentes com propriedade masterBind e nome a ser bindado, isso é apenas uma idéia que tenho na cabeça!

Abraço

13 07 2009
markyhitchhiker

Se eu entedesse melhor sua idéia até implementaria.

Se quiser me ajudar e explicar mais um pouco.

11 01 2010
Antonio Lucas

Ola Marky,

belo trabalho =)

acho que o que o Alexandre (ou Aelxandre) quis dizer era pra qdo designarmos que um frame esta associado a uma determinada classe (um model de um BD) , entao poderiamos adicionar os TextField com o mesmo name dos campos da model, e o Binder faria todo o resto, sem termos de adicionar uma a uma as associacoes =)

11 01 2010
markyhitchhiker

Eu entendi isso.

O caso é que se voce usou um GUI builder que nem do NetBeans o nome dos campos podem ser bem diferentes do atributo das classes, eu até tinha feito com essa possibilidade mas decedi mudar por que quando eu tiver tempo pretendo implementar um Validator junto com isso, e voce passa tudo pelo name do JComponent.

15 09 2009
Flavio

Parabens pelo blog e pela iniciativa!
Muito bom, nivel tecnico altissimo
vou indica-lo para vários amigos programadores

22 01 2010
Antonio Lucas

Ola Marky,

Eu to tendo o seguinte erro com o Binder:

Exception in thread “AWT-EventQueue-0″ java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1937)
at mark.utils.cfg.StringConfiguration.map(StringConfiguration.java:26)
at mark.utils.cfg.StringConfiguration.(StringConfiguration.java:18)
at mark.utils.bind.Binder.(Binder.java:67)
at view.client.Cadastro.(Cadastro.java:67)

a linha 67 eh essa:
binder = new Binder(jPanel1,Client.class,new IntFormatter());
jPanel1 eh o panel que contem os campos que serao usados pro binding.

Eu usei o netbeans pra construir telas (ok, pode chamar de preguicoso =p), mas setei os nomes dos campos corretamente. Eu preciso setar o nome dos campos que nao serao usados pelo Binder? O ResourceBundle que o netbeans cria afeta de alguma forma o Binder.

PS.: Vc desistiu de hospedar o teu codigo em algum lugar? Acho que vale a pena =)

23 01 2010
Antonio Lucas

Bem, acho que o grouplayout (que o netbeans usa por padrao quando usamos o matisse) que era o problema. Troquei para GridBagLayout e voltou a funcionar. Valeu Marky, e desculpa ta enchendo teus comentarios com minhas duvidas =p

27 01 2010
eliangela

Olá Marky!

Sempre estou no GUJ e resolvi dar uma passada aqui no seu blog.
Queria muito saber como que vc usa esse Syntax Highlight. Estou procurando há muitos dias e não consegui ainda.

Obrigada

29 01 2010
Diego Freire

Muito útil essa classe Binder, visto quando se tem uma quantidade enorme de componentes(JTextField) no form, mais eu tenho uma dúvida:

e quando se tratar de componentes do tipo JRadioButton, JComboBox, JCheckBox por exemplo? Não consegui fazer um exemplo funcional, se puderes postar alguma coisa com esses tipos de componentes será muito útil porque geralmente um form também possui esses “fields”…

Agradeço desde já e parabéns pela iniciativa!

1 03 2010
markyhitchhiker

Infelizmente não terminei o Binder ainda, e por enquanto apenas JTextComponents podem ser linkados com os objetos, fora o fato que ainda vou unir um Validator junto para aceitar apenas dados validos.

28 12 2010
Binder – Atualizando objetos facilmente. « MarkyHitchhiker's Blog

[...] Acesse com este novo link. [...]

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s




Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

Junte-se a 150 outros seguidores

%d blogueiros gostam disto: