Projeto Towel: AutoFiltro em JTable

O auto-filtro ordena apenas a visualização.

O máximo que ele fornece é um método que te retorna o índice de todos os índices do model, na ordem que aparecem na view. Com esse método você pode todos os objetos, com todos os campos deles (sendo mostrados ou não) na ordem que o usuário deixou.

Ah ta, entendi… valew então…
Obrigado.

Olá, aproveitando o gancho, gostaria de saber se através deste projeto, tem como que definir o tamanha das colunas da tabela?

Grato,

Resolvido… Vlw a inspiração…

Bom dia a todos.

Vini ou Marky, eu gostaria de uma opinião de vcs.

Eu precisava formatar a data apresentada no table (utilizando o model do Vini - com AutoFiltro), daí eu fiz da seguinte forma.

No ENUM que eu defino as colunas do meu table

DATA_PROCESSAMENTO("Data Processamento")  
	   {  
	       public Object getValue(PowerUP p)  
	       {  
	           return new DataString().formataData(p.getData_processamento());  // chamo a classe para formatar...
	       }
	   };

Classe que formata a data

public class DataString {
	private final DateFormat FORMATAR = new SimpleDateFormat("dd/MM/yyyy");
	
	public Object formataData(Object date){
		return FORMATAR.format(date);
	}
}

É uma boa prática da forma que eu desenvolvi? Funcionou corretamente, mas eu me preocupo em não fazer gambiarras.

Vlw

Olá,
estou utilizando o ObjectTableModel do marky com o TableFilter do Vini, estou trabalhando com uma tela única para realizar as pesquisas,
para isto estou criando/configurando os models desta forma:

[code]public static TableFilter modelCidade(JTable table){
AnnotationResolver resolver = new AnnotationResolver(Cidade.class);
cidadeModel = new ObjectTableModel<Cidade>(
resolver, “nomeCidade,nomeEstado,paisEstado”);
filterCidade = new TableFilter(table.getTableHeader(),
cidadeModel);
return filterCidade;
}

public static TableFilter modelContato(JTable table){
AnnotationResolver resolver = new AnnotationResolver(Contato.class);
contatoModel = new ObjectTableModel<Contato>(
resolver, “nomeContato,emailContato,telefoneContato,nomePessoa”);
filterContato = new TableFilter(table.getTableHeader(),
contatoModel);
return filterContato;
}[/code]
Na minha tela de pesquisa eu crio uma única instância da JTable:

Quando seleciono o cadastro que desejo pesquisar (faço isso em um JComboBox) a tela atualiza as colunas conforme o model selecionado,
o código responsável por isso é o seguinte:

public void setTipoPesquisa() { codigoSelecionado = -1; jcbTipoPesquisa.setSelectedItem(cadastroPesquisa); if (cadastroPesquisa.equals(BD.EstruturaBanco.CIDADE)) { table.setModel(telasPesquisa.TableModels.modelCidade(table)); } else if (cadastroPesquisa.equals(BD.EstruturaBanco.CONTATO)) { table.setModel(telasPesquisa.TableModels.modelContato(table)); } this.setTitle("Pesquisa de " + cadastroPesquisa); jbTodos.setToolTipText("Pesquisar por todos os registros de " + cadastroPesquisa); Resizer.fitAllColumns(table); }

Más estou com um problema, está dando um erro no ArrayList quando faço a troca do model com 3 colunas para o de 4 colunas,
imagino que eu saiba o por que do erro, más não sei como corregi-lo, alguém pode me ajudar?

PS.: Quando troco de um model com 3 colunas para outro com o mesmo numero de colunas não ocorre erro.

segue o erro:

Exception occurred during event dispatching: java.lang.IndexOutOfBoundsException: Index: 3, Size: 3 at java.util.ArrayList.RangeCheck(ArrayList.java:547) at java.util.ArrayList.get(ArrayList.java:322)

Vc tem que verificar se esta correto essa troca de model’s (3 colunas por 4), pois esse log de erro eh justamente a tentativa de acesso de uma posição inválida na lista. Eu não sei como vc esta chamando na view, e pelo q eu entendi o usuário pode trocar de model conforme ele queira. Será que vc não tem q remover o model anterior antes de adicionar o novo? Eu não tenho certeza, mas talvez ele esta tentando colocar um model “em cima” do outro. Não conheço o model do Mark, pois eu uso o do Viny, mas ta uma idéia pra vc.

então caceres, justamente isso que eu não sei como fazer,
já tinha pesquisado sobre o erro, e você está certo, más justamente isso que eu disse, não sei como fazer isso,
tem alguma forma de remover o model?
tentei fazer uma remoção das colunas, mas da forma que eu fiz, o erro persiste.

alguém? :cry:

Cara, nunca vi esse erro acontecer nessas circunstancias. Será que não é nenhum problema ao carregar seus dados?

Como teste, troque de um model para outro vazio e veja se ocorre o problema.

marky, o pior é que já fiz isso,
e também quando troco de um model com mais colunas que o que vou adicionar não da erro algum,
somente da esse erro quando troco de um model menor para um maior… =[

na verdade nem carrego dados na tabela quando seto o model,
só irão ser adicionados valores (linhas) a tabela depois de digitar
alguma coisa no field ou clicar no botao pesquisar todos.

como o erro persiste depois de muitas tentativas de correção resolvi postar o erro completo,
para que assim talvez vocês possa me ajudar… desconfio que seja algo com o tablefilter,
algo que eu esteja fazendo de forma errónea?

Exception occurred during event dispatching: java.lang.IndexOutOfBoundsException: Index: 3, Size: 3 at java.util.ArrayList.RangeCheck(ArrayList.java:547) at java.util.ArrayList.get(ArrayList.java:322) at Testes.Table.util.gui.table.headerPopup.TableHeaderPopup.getPopup(TableHeaderPopup.java:199) at Testes.Table.util.gui.table.TableFilter.refreshHeader(TableFilter.java:151) at Testes.Table.util.gui.table.TableFilter.access$100(TableFilter.java:35) at Testes.Table.util.gui.table.TableFilter$3.columnAdded(TableFilter.java:139) at javax.swing.table.DefaultTableColumnModel.fireColumnAdded(DefaultTableColumnModel.java:516) at javax.swing.table.DefaultTableColumnModel.addColumn(DefaultTableColumnModel.java:108) at javax.swing.JTable.addColumn(JTable.java:2772) at javax.swing.JTable.createDefaultColumnsFromModel(JTable.java:1263) at javax.swing.JTable.tableChanged(JTable.java:4373) at javax.swing.JTable.setModel(JTable.java:3675) at Testes.TelaPesquisa.setTipoPesquisa(TelaPesquisa.java:219) at Testes.TelaPesquisa$1.actionPerformed(TelaPesquisa.java:137) at javax.swing.JComboBox.fireActionEvent(JComboBox.java:1240) at javax.swing.JComboBox.setSelectedItem(JComboBox.java:567) at javax.swing.JComboBox.setSelectedIndex(JComboBox.java:603) at javax.swing.plaf.basic.BasicComboPopup$Handler.mouseReleased(BasicComboPopup.java:817) at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:273) at java.awt.Component.processMouseEvent(Component.java:6263) at javax.swing.JComponent.processMouseEvent(JComponent.java:3267) at javax.swing.plaf.basic.BasicComboPopup$1.processMouseEvent(BasicComboPopup.java:481) at java.awt.Component.processEvent(Component.java:6028) at java.awt.Container.processEvent(Container.java:2041) at java.awt.Component.dispatchEventImpl(Component.java:4630) at java.awt.Container.dispatchEventImpl(Container.java:2099) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168) at java.awt.Container.dispatchEventImpl(Container.java:2085) at java.awt.Window.dispatchEventImpl(Window.java:2478) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:178) at java.awt.Dialog$1.run(Dialog.java:1046) at java.awt.Dialog$3.run(Dialog.java:1098) at java.security.AccessController.doPrivileged(Native Method) at java.awt.Dialog.show(Dialog.java:1096) at java.awt.Component.show(Component.java:1563) at java.awt.Component.setVisible(Component.java:1515) at java.awt.Window.setVisible(Window.java:842) at java.awt.Dialog.setVisible(Dialog.java:986) at Testes.TelaPesquisa.&lt;init&gt;(TelaPesquisa.java:91) at Testes.TelaPesquisa.abreTela(TelaPesquisa.java:284) at asf_automation_system_farms.TelaPrincipal.actionPerformed(TelaPrincipal.java:135) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242) at javax.swing.AbstractButton.doClick(AbstractButton.java:357) at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:1223) at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:1264) at java.awt.Component.processMouseEvent(Component.java:6263) at javax.swing.JComponent.processMouseEvent(JComponent.java:3267) at java.awt.Component.processEvent(Component.java:6028) at java.awt.Container.processEvent(Container.java:2041) at java.awt.Component.dispatchEventImpl(Component.java:4630) at java.awt.Container.dispatchEventImpl(Container.java:2099) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168) at java.awt.Container.dispatchEventImpl(Container.java:2085) at java.awt.Window.dispatchEventImpl(Window.java:2478) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Primeiro parabéns por esse projeto, muito interessante o ObjectTableModel e o Auto-Filtro, eu inclusive havia criado um modelo de tabela chamado de ObjectTableModel por não conhecer esse… :oops:

Só teve uma coisa que eu não gostei no auto-filtro, quando é usado algum look and feel que tem borda em labels, como o Nimbus por exemplo, o header fica meio estranho, parecendo que tem borda só no label…

Pra deixar mais bonito, em vez de colocar um JToggleButton na classe TableHeaderPopup, eu adicionei um icone no label.
Acho que o ideal é o botão, mas eu não consegui resolver isso usando um botão :cry:

Se resolver lançar uma nova versão e tiver tempo, da uma olhada nisso :lol:

E pra quem está tendo o mesmo “problema” que eu segue o que eu alterei.

            panel.add(label, gridBagConstraints);
            label.setHorizontalTextPosition(JLabel.LEFT);
            ImageIcon icon = null;
            
            if (modified.get(modelIndex) == null || !modified.get(modelIndex))
            	icon = new ImageIcon(getClass().getResource(
                  "/res/gui/down.gif"));
            else
            	icon = new ImageIcon(getClass().getResource(
                  "/res/gui/down_red.gif"));
            FontMetrics fm = table.getFontMetrics(table.getFont());
            label.setIconTextGap(table.getColumnModel().getColumn(column).getWidth() - (fm.stringWidth(label.getText()) + 20));
            label.setIcon(icon);
            
//            JToggleButton button = new JToggleButton();

//            if (modified.get(modelIndex) == null || !modified.get(modelIndex))
//                button.setIcon(new ImageIcon(getClass().getResource(
//                        "/res/gui/down.gif")));
//            else
//                button.setIcon(new ImageIcon(getClass().getResource(
//                        "/res/gui/down_red.gif")));
//
//            button.setPreferredSize(new Dimension(16, 16));
//            button.setMaximumSize(new Dimension(16, 16));
//            button.setMinimumSize(new Dimension(16, 16));
//            button.setFocusable(false);
//            button.setSelected(column == selected);

//            panel.add(button, new GridBagConstraints());
//
//            Border border = label.getBorder();//UIManager.getBorder("TableHeader.cellBorder");
//            	//border.getBorderInsets(c).set(0, 2, 1, 1);
//            panel.setBorder(border);
//            label.setBorder(null);
//            //jLA
           

            return label;

E mais uma vez, parabéns pelo projeto :smiley:

Cara muito bacana o Auto-Filtro mas eu quero saber se tem como eu adicionar um novo filtro tipo onde eu escolha de tal dia até tal dia e ele deixe no grid apenas os registros pertencentes periodo, queria saber se é possivel implementar isso na classe TableFilter se sim deem uma dica to perdido aqui.

Marky.Vasconcelos,

Estava tentando utilizar a sua classe
http://code.google.com/p/markutils/source/browse/trunk/src/mark/utils/swing/table/Resizer.java
para ajustar a largura da coluna conforme o conteúdo carregado no model, mas não funcionou aqui.

Fiz algumas mudanças, mas apenas para conteúdo onde é String. Segue o código abaixo.

[code]import javax.swing.JTable;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

public class Resizer {

private static final int STRING_WIDTH = 6;
/**
 * Método que ajuasta a coluna conforme da JTable conforme o tamanho do
 * conteúdo carregado no model
 * 
 * @param coluna
 *            Recebe a coluna que sera redimensionada
 * @param margin
 *            espaço de bonus colocado caso a contagem dos campos esteja
 *            errada
 * @param tabela
 *            tabela que será implementada o redimensionamento
 */

public static void fitColumn(int coluna, JTable tabela) {
	TableColumnModel colModel = tabela.getColumnModel();
	TableColumn col = colModel.getColumn(coluna);
	TableModel model = tabela.getModel();
	int chars = 0;
	for (int i = 0; i &lt; model.getRowCount(); i++) {
		Object value = tabela.getValueAt(i, coluna);
		if (value instanceof String) {
			String text = (String) value;
			if (text.length() &gt; chars) {
				chars = text.length();
			}
		}
	}
	col.setMinWidth(chars * STRING_WIDTH);
}

public static void fitAllColumns(JTable table) {
	TableColumnModel colModel = table.getColumnModel();
	for (int i = 0; i &lt; colModel.getColumnCount(); i++)
		fitColumn(i, table);
}

}[/code]

jean.zunino
Isso era um probleminha conhecido que ficou de ser visto nas futuras revisões.

[quote=javer]Na verdade tenho mais uma pergunta.

Onde eu trato a formatação do dado adicionado naquele popUP da coluna, na imagem tem uma coluna do tipo Date que quero mostrar a data no formato: dd/MM/yyyy

Eu (ainda) não consegui localizar nos código onde está sendo feito isso, e também como converter de volta quando for selecionado pelo usuário para atualizar o filtro.[/quote]

Gostaria de parabenizar ao Vini Godoy pela iniciativa de criar o Table Filter.
Estou utilizando em minha aplicação e tem me ajudado bastante.
Porém, estou com uma dúvida, estou querendo alterar a descrição do Pop Up dos filtros para português PT -BR.
Dei uma olhada na api e não encontrei como faz isto…