lucas.sistemas:
Rafael obrigado pela dica, nunca mexi com o FocusTraversalPolicy, você poderia dar um exemplo de código?
Crie uma Classe que Estenda FocusTraversalPolicy... parecida com essa:
import java.awt.Component;
import java.awt.Container;
import java.awt.FocusTraversalPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
public class MyTraversalPolice extends FocusTraversalPolicy {
private List<MyJTextField> componentes;
private int currentIndex = 0;
@Override
public Component getComponentAfter(Container container, Component component) {
if(canLostFocusRule(component)){
//Retorna o proximo;
if(this.currentIndex < this.componentes.size()){
return this.componentes.get( ++ this.currentIndex);
}
else{
return getFirstComponent(container);
}
}
else{
//Retorna o proprio componete que está perdendo o foco.
return component;
}
}
@Override
public Component getComponentBefore(Container container, Component component) {
if(canLostFocusRule(component)){
//Retorna o anterior;
if(this.currentIndex < this.componentes.size()){
return this.componentes.get( -- this.currentIndex);
}
else{
return getLastComponent(container);
}
}
else{
//Retorna o proprio componete que está perdendo o foco.
return component;
}
}
@Override
public Component getDefaultComponent(Container container) {
return getFirstComponent(container);
}
@Override
public Component getFirstComponent(Container container) {
this.currentIndex = 0;
return this.componentes.get(this.currentIndex);
}
@Override
public Component getLastComponent(Container container) {
this.currentIndex = this.componentes.size() -1;
return this.componentes.get(currentIndex);
}
/**
* Default para add components
* @param component
*/
public void addComponentToList(Component component){
if(this.componentes == null){
this.componentes = new ArrayList<MyJTextField>();
}
this.componentes.add((MyJTextField) component);
}
/**
* JSpinner é um Component composto de JAbstractButons e JFormatedTextFild que você tem que extrair
* @param component
*/
public void addComponentToList(JSpinner component){
Component []spinnerParts = component.getEditor().getComponents();
//que os pedaços do spinner (caixa de text e botões e add na lista)
//addComponentToList("pedaço do spinner que vai ganhar foco");
}
/**
* JRadioButton é o Component composto de JAbstractButons que você tem que extrair
* @param component
*/
public void addComponentToList(JRadioButton component){
//Sua impletemtação se precisar
}
public void addComponentsToList(List<Component> components){
for (Component component : components) {
addComponentToList(component);
}
}
/**
* Verifica se seu component implementa a Inteface que obriga ter validador.
* Se não permite o foco passar.
* @param component
* @return
*/
private boolean canLostFocusRule(Component component){
Class []interfaces = component.getClass().getInterfaces();
if(component.getParent() instanceof JSpinner){
return ((MyJTextField)component.getParent()).doValidate();
}
else if(interfaces != null && -1 < Arrays.binarySearch(interfaces, MyJTextField.class)){
return ((MyJTextField)component).doValidate();
}
return true;
}
}
Essa Classe faz o controle de navegação de todos dos compenents que estão na lista. (Navegação por tabulação - Ela NÃO sobrescreve o evento de focos por clique de mouse, diferente o InputVerifier)
Beleza, mas ainda você precisa validar seus components. Dai que vem o truque...
Não use os componentes nativos do Javax.swing... crie subclasses desses components que tenham um implementação obrigatória de focos. Entendeu? Não... vamos lá...
Primeiramente precisamos de uma interface que obrigue TODOS os seus components de telas que o usuário vão inserir dados ter um validador...
public interface MyInputComponentsInterface {
public boolean doValidate();
}
Agora invez de usar o JTextField por exemplo... Criaremos uma subclasse que estenda JTextField e implemente MyInputComponentsInterface e bingo:
import javax.swing.JTextField;
public class MyJTextField extends JTextField implements
MyInputComponentsInterface {
@Override
public boolean doValidate() {
return false;
}
}
Só precisaremos implementar o método doValidade() com a validação de campo que você precisar.
Vamos supor que no seu caso, você só precisa obrigar que o campo não estar vazio. Então faremos a seguinte validação:
@Override
public boolean doValidate() {
if(getText() != null && getText().trim().length() != 0){
return true;
}
return false;
}
Se tiver algum valor no JTextField o método retorna TRUE para o chamador (no caso a classe MyTraversalPolice no método canLostFocusRule).
Lembrando que é recomendável criar uma subclasse para cada tipo de component que for usar e for validar. JTextField, JFormatedTextField, JComboBox e outros. MAS CUIDADO especial com JCOMBOBOX, JRADIOBUTTON, JSPINNER que são components compostos (Um panel com JTextField e AbstraticButtons dentro).
Quando for Inserir inserir esses caras... decida-se antes qual pedaço vai receber o FOCO. (Veja o métodos addComponentToList(JSpinner component) e canLostFocusRule(Component component) da classe MyTraversalPolice)
No JPanel que tem seus components. Depois de instanciar todos eles coloque:
this.setFocusTraversalPolicy(new MyTraversalPolice());
Como eu disse... é chato. Mas uma vez feito. Você pode usar esse comportamento pra todas as telas e usar em vários outros projeto!!!
Abraço