Adicionar colunas a TableModel personalizado [RESOLVIDO]
11 respostas
L
LeonardoU
Bom dia pessoal!
Fiz algumas buscas ao GUJ, mas não encontrei nada relativo a este assunto. Tenho meu table modelo personalizado (exemplo ViniGodoy), porém necessito adicionar colunas dinamicamente, e não sei como fazer. Se alguém puder repassar um exemplo, agradeço.
Você realmente precisa adicionar uma coluna, ou é suficiente simplesmente esconder a coluna e mudar o título?
L
LeonardoU
Obrigado por retornar entanglement . Realmente necessito adiciona-las em tempo de execução. Isto de acordo com os paramentros do item que foi selecionado pelo usuário (JComboBox).
E
entanglement
Nesse caso, provavelmente você terá de criar um TableModel que seja um ArrayList de ArrayLists (não exatamente um ArrayList de objetos de uma determinada classe, que é o padrão para as tabelas com TableModel personalizado).
Uma vez que você chamou o combo, as colunas da tabela poderão ser alteradas ou não? (Por exemplo, ele é um retorno de uma consulta SQL que você escolheu via combo?)
Se o combo tiver poucas alternativas e a cada alternativa estiver associada uma determinada classe, você pode criar um TableModel diferente para cada alternativa, e então associar dinamicamente esse TableModel ao JTable.
L
LeonardoU
Tanto os itens listados no combo, como os parametros, determinam as colunas exibidas são retornados de uma query. A quantidade de colunas “adicionais” que posso necessitar pode variar de 0 a 15, podendo gerar inúmeras combinações de colunas. Andei observando a classe DefaultTableModel (infelizmente) e a mesma possui os metodos para adicionar ou remover colunas, mas estou tentando evitar o uso da mesma. Muito obrigado pela resposta Sr. entanglement. Abraço.
E
entanglement
No seu caso, talvez fosse mais fácil ter um ArrayList de ArrayList. Não use DefaultTableModel porque ele é um Object[][], o que indica que você não consegue adicionar linhas de maneira trivial (você se lembra que um array não pode ser expandido ou diminuído).
L
LeonardoU
Certo, vou tentar implementa-lo, muito obrigado. Talvez, possui algum exemplo?
A
al.barbosa
Leonardo,
Segue um exemplo. Fiz alguns testes, mas como implementei a pouco tempo acho que ainda precisa testar mais. Pode melhorar ainda. Por exemplo: podem ser adicionados métodos para remover linhas e colunas.
entanglement, é isto mesmo que você estava sugerindo?
TableModel:
importjava.util.ArrayList;importjava.util.List;importjavax.swing.table.AbstractTableModel;importjavax.swing.table.TableModel;publicclassModelFlexextendsAbstractTableModel{privateList<String>cabecalho=newArrayList();privateList<List<Object>>linhas=newArrayList();privateList<Class>classes=newArrayList();publicModelFlex(ArrayList<String>cabecalho,ArrayList<Class>classes){if(cabecalho.size()!=classes.size()){thrownewIllegalArgumentException("Quantidade de colunas diferente da quantidade de classes.");}this.cabecalho=(List<String>)cabecalho.clone();this.classes=(List<Class>)classes.clone();}publicStringgetColumnName(intcol){returncabecalho.get(col);}publicintgetRowCount(){returnlinhas.size();}publicintgetColumnCount(){returncabecalho.size();}publicObjectgetValueAt(introw,intcol){returnlinhas.get(row).get(col);}publicClassgetColumnClass(intcol){returnclasses.get(col);}publicvoidaddRow(ArrayList<?extendsObject>valores){if(valores.size()!=cabecalho.size()){thrownewIllegalArgumentException("Quantidade de valores diferente da quantidade de colunas.");}for(intcoluna=0;coluna<valores.size();coluna++){validar(coluna,valores.get(coluna));}ArrayList<Object>linha=newArrayList();for(Objectvalor:valores){linha.add(valor);}linhas.add(linha);fireTableDataChanged();}publicvoidaddColumn(Stringtitulo,Classclasse){//adiciono a nova coluna no cabecalhocabecalho.add(titulo);//adiciono a classe da nova colunaclasses.add(classe);//adiciono os valores da nova coluna em cada linhafor(List<Object>valores:linhas){try{valores.add(classe.newInstance());}catch(ReflectiveOperationExceptionex){thrownewIllegalArgumentException("Nao foi possivel instanciar a classe "+classe.getName());}}fireTableStructureChanged();}//cria uma coluna com valor defaultpublicvoidaddColumn(Stringtitulo,Classclasse,ObjectvalorDefault){//adiciono a nova coluna no cabecalhocabecalho.add(titulo);//adiciono a classe da nova colunaclasses.add(classe);//adiciono os valores da nova coluna em cada linhafor(List<Object>valores:linhas){valores.add(valorDefault);}fireTableStructureChanged();}privatevoidvalidar(intcol,Objectvalor){if(!valor.getClass().equals(classes.get(col))){thrownewIllegalArgumentException("Valor na coluna "+col+" deve ser do tipo "+classes.get(col).toString());}}}
Formulario com a tabela:
importjava.awt.Container;importjava.awt.Dimension;importjava.awt.FlowLayout;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.util.ArrayList;importjava.util.List;importjavax.swing.JButton;importjavax.swing.JFrame;importjavax.swing.JOptionPane;importjavax.swing.JScrollPane;importjavax.swing.JTable;publicclassFormTabelaextendsJFrame{ModelFlexmodel;finalJTabletabela;ArrayList<String>cabecalho;ArrayList<Class>classes;intquantLinhas=0;publicstaticvoidmain(String[]args){FormTabelaft=newFormTabela();ft.setVisible(true);}publicFormTabela(){super("Tabela que permite incluir colunas");Containerc=getContentPane();c.setLayout(newFlowLayout());cabecalho=newArrayList();cabecalho.add("Codigo");cabecalho.add("Telefone");classes=newArrayList();classes.add(Integer.class);classes.add(String.class);model=newModelFlex(cabecalho,classes);tabela=newJTable(model);tabela.setPreferredScrollableViewportSize(newDimension(450,200));JScrollPanescrollPane=newJScrollPane(tabela);c.add(scrollPane);JButtonincluirLinha=newJButton("Incluir Linha");incluirLinha.addActionListener(newActionListener(){publicvoidactionPerformed(ActionEvente){ArrayList<Object>linha=newArrayList();quantLinhas++;for(intcoluna=0;coluna<cabecalho.size();coluna++){if(classes.get(coluna).equals(String.class)){linha.add(cabecalho.get(coluna)+" "+quantLinhas);}elseif(classes.get(coluna).equals(Integer.class)){linha.add(newInteger(quantLinhas));}}model.addRow(linha);}});c.add(incluirLinha);JButtonincluirColuna=newJButton("Incluir Coluna");incluirColuna.addActionListener(newActionListener(){publicvoidactionPerformed(ActionEvente){Stringnome=JOptionPane.showInputDialog(null,"Digite o nome da nova coluna:");if(nome!=null){cabecalho.add(nome);classes.add(String.class);model.addColumn(nome,String.class);}}});c.add(incluirColuna);setSize(500,400);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setVisible(true);}}
L
LeonardoU
Alcebiades, o salvador da Pátria, hehe.
Exatamente isto que precisava, testei, funcionou perfeitamente, agora irei adaptar ao projeto. Parabéns, e obrigado pela resposta. Tópico resolvido.
L
LeonardoU
Reabrindo o tópico. Necessito implementar o metodo setValueAt(Object aValue, int rowIndex, int columnIndex). Tentei deste modo, os valores chegam ao metodo corretamente, mas os valores não são alterados no model. Alguém tem ideia como fazer?