TableModel no JTable

12 respostas
R

Pessoal me desculpem se estou duplicando Tópico, mas todas as formas que eu pesquisei para resolver meu problema não deram certo. Estou com dificuldade para fazer o seguinte:

Tenho minha classe ProdutoTableModel, copiei um modelo do nosso amigo ViniGodoy (muito bem explicado, meus agradecimentos) e adaptei para o meu. Tenho a View com alguns TextField’s e o JTable.

1-Estou com muita dificuldade para chamar essa classe ProdutoTableModel na View, pra dentro do JTable. Tenho que publicar um metodo para chamar? Como seria?

2-Depois quero que os dados digitados nos TextField’s vão para a tabela. Tenho um botão “Incluir”, implementando um Action nele qual sintaxe deveria utilizar para direcionar os JTextFiel’s para as linhas das colunas?

3-Logo depois salvar estes dados da tabela no banco de dados. Como devo setar essas linhas e colunas para serem gravados no banco?

4-Outra coisa, tenho um metodo “mostar_dados”, nele quando o usuario abre a tela aprecem os dados do ultimo registro nos JtextFiel’s. Como faço para aparecer também os dados no JTable?

Consigo fazer algumas dessas usando o DefaultTableModel. E seguindo orientações dos colegas optei por usar meu proprio modelo. No DefautTableModel eu não conseguia gravar mais de uma linha no banco de dados.

Gostaria que me ajudassem postando exemplos, direcionando link’s. Por favor.

Desde já agradeço!

12 Respostas

V

Leia com atenção a descrição dos fóruns antes de abrir tópicos. Esse tópico não é de java básico, e sim, de interface gráfica. Vou move-lo.

1. Você está fazendo sua View pelo Netbeans, Visual Editor do Eclipse, ou na unha? 2. Você monta um objeto usando os JTextFields e adiciona esse objeto ao model.
//Criamos um produto
Produto p = new Produto();
p.setNome(txtNome.getText());
p.setDescricao(txtDescricao.getText());

//Chamamos o DAO para salva-lo no banco
if (new ProdutoDao().salvar(p)) {
   JOptionPane.showMessageDialog(this, "Produto inserido com sucesso!");
}

//Adicionamos o produto na tabela
ProdutoTableModel model = (ProdutoTableModel) tblProduto.getModel();
model.add(p);

3. Já respondido na questão anterior.

4. Não entendi. Os dados já estão dentro do JTable e você só quer mudar a posição do item selecionado? Ou os dados não estão no JTable e precisam ser inseridos?

Você pode fazer tudo o que você faz com um modelo próprio usando o Default. Porém, o default é mais lento, mais pesado e muito mais difícil de usar.

R

Desculpa. Fico muito agradecido pela atenção.

1-Fiz com o VisualEditor do Eclipse.

2-Este trecho é para ser implementado no Action do Botão Incluir né!?

3-Todos os dados do Registro, botão “Fechar Venda”. Os JTextFiel’s eu consigo gravar, quero gravar também todas as linhas da tabela. Tenho uma classe especifica para conexão com o banco, devo organizar ela na view ou no TableModel.

Eu não estou conseguindo entender como posso declarar as ações do TableModel na View.

Por favor, confira o código.

Produto

public class Produto {

 	    private String table0_descricao;
	    private double table1_precounitario;
	    private int table2_quantidade;
	    private double table3_subtotal;

	    public Produto() {
	    }

	    public Produto(String table0_descricao, double table1_procounitario, int table2_quantidade, double table3_subtotal ) {
	        this.table0_descricao = table0_descricao;
	        this.table1_precounitario = table1_procounitario;
	        this.table2_quantidade = table2_quantidade;
	        this.table3_subtotal = table3_subtotal;
	    }

	    public Produto(int i, String string, int j) {
			// TODO Auto-generated constructor stub
		}

		public String getTable0_Descricao() {
	        return table0_descricao;
	    }

	    public void setTable0_Descricao(String table0_descricao) {
	        this.table0_descricao = table0_descricao;
	    }

	    public double getTable1_PrecoUnitario() {
	        return table1_precounitario;
	    }

	    public void setTable1_PrecoUnitario(double table1_precounitario) {
	        this.table1_precounitario = table1_precounitario;
	    }

	    public int getTable2_Quantidade() {
	        return table2_quantidade;
	    }

	    public void setTable2_Quantidade(int table2_quantidade) {
	        this.table2_quantidade = table2_quantidade;
	    }
	    
	    public double getTable3_Subtotal() {
	        return table3_subtotal;
	    }

	    public void setTable3_SubTotal(double table3_subtotal) {
	        this.table3_subtotal = table3_subtotal;
	    }

}

ProdutoTableModel

public class ProdutoTableModel extends AbstractTableModel  {    
    private List<Produto> linhas;  
   
    private String[] colunas = new String[] {  
            "Decrição do Produto", "Preço Unitário", "Quantidade", "SubTotal"};  
    
    public ProdutoTableModel() {  
        linhas = new ArrayList<Produto>();  
    }  
       
    public ProdutoTableModel(List<Produto> ListaDeProduto) {  
        linhas = new ArrayList<Produto>(ListaDeProduto);  
    }  

    @Override  
    public int getColumnCount() {  
  
        return colunas.length;  
    }  
  
    /* Retorna a quantidade de linhas. */  
    @Override  
    public int getRowCount() {  
        // Retorna o tamanho da lista de produtos.  
        return linhas.size();  
    }  
  
    @Override  
    public String getColumnName(int columnIndex) {  
 
        return colunas[columnIndex];  
    };  
  
    /* Retorna a classe dos elementos da coluna especificada. 
     * Este método é usado pela JTable na hora de definir o editor da célula. */  
    @Override  
    public Class<?> getColumnClass(int columnIndex) {  
        // Retorna a classe referente a coluna especificada.  
        // Aqui é feito um switch para verificar qual é a coluna  
        // e retornar o tipo adequado. As colunas são as mesmas  
        // que foram especificadas no array "colunas".  
        switch (columnIndex) {  
        case 0: // Primeira coluna é a Descrição, que é um String.  
            return String.class;  
        case 1: // Segunda coluna é o PreçoUnitario, que é um double.  
            return double.class;  
        case 2: // Terceira coluna é a Quantidade, que é int  
            return int.class;  
        case 3: // Quarta coluna é o SubTotal, que é double  
                return double.class;  
         
        default:    
            throw new IndexOutOfBoundsException("columnIndex out of bounds");  
        }  
    }  
  
    /* Retorna o valor da célula especificada 
     * pelos índices da linha e da coluna. */  
    @Override  
    public Object getValueAt(int rowIndex, int columnIndex) {  
        // Pega o produto da linha especificada.  
        Produto prod = linhas.get(rowIndex);  
  
        // Retorna o campo referente a coluna especificada.  
        // Aqui é feito um switch para verificar qual é a coluna  
        // e retornar o campo adequado. As colunas são as mesmas  
        // que foram especificadas no array "colunas".  
        switch (columnIndex) {  
        case 0: // Primeira coluna é a Descrição.  
            return prod.getTable0_Descricao();  
        case 1: // Segunda coluna é o PreçoUnitario.  
            return prod.getTable1_PrecoUnitario();  
        case 2: // Terceira coluna é a Quantidade.  
            return prod.getTable2_Quantidade();  
        case 3: // Quarta coluna é o SubTotal.  
            return prod.getTable3_Subtotal();  
                 
        default:  
 
            throw new IndexOutOfBoundsException("columnIndex out of bounds");  
        }  
    }  
  

    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {  
            // Pega o jogador da linha especificada.  
        Produto prod = linhas.get(rowIndex);  

        switch (columnIndex) {  
        case 0: // Primeira coluna é a Descrição.  
                        if (aValue.getClass() == int.class)  
            prod.setTable0_Descricao(aValue.toString());  
        case 1: // Segunda coluna é o PreçoUnitario.  
                        if (aValue.getClass() == String.class)  
            prod.setTable1_PrecoUnitario(Double.parseDouble (aValue.toString()));  
        case 2: // Terceira coluna é a Quantidade  
                        if (aValue.getClass() == String.class)  
            prod.setTable2_Quantidade(Integer.parseInt(aValue.toString()));  
        case 3: // Quarta coluna é o SubTotal  
                        if (aValue.getClass() == int.class)  
            prod.setTable3_SubTotal(Double.parseDouble(aValue.toString()));  
                
              
        default:  
 
            throw new IndexOutOfBoundsException("columnIndex out of bounds");  
        }  
        }  
   
    @Override  
    public boolean isCellEditable(int rowIndex, int columnIndex) {  
        return false;  
    }  
  
    /* Retorna o produto da linha especificada. */  
    public Produto getProduto(int indiceLinha) {  
        return linhas.get(indiceLinha);  
    }  
  
    /* Adiciona um registro. */  
    public void addProduto(Produto prod) {  
      
        linhas.add(prod);  
  
      
        int ultimoIndice = getRowCount() - 1;  
  
    
        fireTableRowsInserted(ultimoIndice, ultimoIndice);  
    }  
  
   
        fireTableRowsDeleted(indiceLinha, indiceLinha);  
    }  
  
        fireTableRowsInserted(tamanhoAntigo, getRowCount() - 1);  
    }  
 
    public void limpar() {  
        // Remove todos os elementos da lista de Produtos.  
        linhas.clear();  
 
        fireTableDataChanged();  
    }
    
  
   
    public boolean isEmpty() {  
        return linhas.isEmpty();  
    }  
}
V

Como está implementado o seu DAO? Você já tem os métodos para salvar e carregar produtos?

R

Saudação ViniGodoy…

Fico grato pela atenção. E admiro muito essa sua disponibilidade de compartilhar o conhecimento, estou na luta para fazer o mesmo.

Aí é que está sendo a “muagem”!!!

Está “cru”!!!

O que eu não estou entendendo direito é a sintaxe que preciso para implementar esses métodos.

Corrija-me se estiver errado. No meu DAO preciso de métodos para chamar os métodos do meu TableModel. No TableModel tem que ter todos os métodos que preciso no meu DOA.
Pelo que entendi quem faz o trabalho é o TableModel, meu DAO vai chamar os métodos que estão implementados no meu TableModel. Então, como devo implementar esses métodos no meu DAO? Pode me explicar, ou dar uma direção para que eu entenda exatamente a sintaxe básica dessas implementação. Tenho navegado aqui no forum e google e nada específico encontrei.

R

Continuação…

“Está crú” no que diz respeito a tabela.

Tenho um método mostar_dados, e para chamar os JTextFiel’s do banco faço isso:

jt_NumVenda.setText(con_NovaVenda.resultset.getString ("numero"));

Como devo implementar a ação mostrar os dados da tabela a tabela ao abrir a tela?

Tenho um boltão salvar, e para eu salvar JTextField’s no banco faço o seguinte:
logo após o insert…

jt_NumVenda.getText() + "','" +
...

Como devo implementar a ação de salvar no banco de dados?

V

Não. O seu DAO tem os métodos que:

  1. Salva produtos no banco;
  2. Obtém listas de produtos do banco;

Basicamente, o DAO é a ponte entre as classes de negócio (Produto) e o banco de dados. O DAO não conversa diretamente com o TableModel. Quem vai fazer essa conversa é o seu JFrame.

Por exemplo, vamos supor que você queira preencher uma tabela com todos os produtos do banco. No seu Dao teria que ter um método chamado obterProdutos(), que lesse as tabelas do banco e montasse com isso uma lista de produtos. Então, seu botão “Consultar” faria algo assim:

//Criamos o DAO e pesquisamos os produtos do banco ProdutoDao dao = new ProdutoDao(); List&lt;Produto&gt; produtos = dao.consultar(); //Criamos um model com esse produtos e o definimos no JTable. ProdutoTableModel model = new ProdutoTableModel(produtos); tblProdutos.setModel(model);

Você sabe usar um banco de dados em Java? Já usou as classes ResultSet, PreparedStatement, Connection, etc?

R

eita… agora que ferrô mesmo.

Para obterprodutos(), tenho um método preencher_jtable(). Este faz o que eu preciso, mas DefaultTableModel.

private void preencher_jtable(){

		DefaultTableModel tabela = (DefaultTableModel)jTable.getModel();
			
		String[] colunas = {"Descrição do Produto", "Preço"};
		tabela.setColumnIdentifiers(colunas);
	
		jTable.setAutoCreateRowSorter(true);
				
		jTable.getColumnModel().getColumn(0).setPreferredWidth(400);
		jTable.getColumnModel().getColumn(1).setPreferredWidth(50);
				
		        try{
		
			while (con_Produtos.resultset.next())
				                         tabela.addRow(new Object[]{
												   con_Produtos.resultset.getString("prod_descricao"),
												   con_Produtos.resultset.getString("prod_precovenda"),
												  
												  });
						con_Produtos.resultset.first();
			
			}catch(Exception erro){
		
				JOptionPane.showMessageDialog(null, "Não foi possível listar dados de registros \n" + erro);
		}
	}

Chamo esse método no initialize() e ele inicia a tabela com os dados do banco.

como seria uma implementação dessa função eu usando TableModel?

Uso as classes ResultSet, PreparedStatement, Connection, etc para outras ocasiões. Minha dúvida é usar nesta ocasião (TableModel).

R

Faltou citar o seguinte…

Esse método preencher_jtable encontra-se dentro de um Frame, que apenas lista os produtos cadastrados e faz pesquisa, clicando no botão referente a coluna ele ordena pela coluna clicada, enfim… Quando o usuario acha o produto e clica essas informações vão para a tela de venda antes de serem lançadas na tabela, o usuario digita a quantidade e o sistema calcula o subtotal, ai sim as informação vão para a tabela.

O usuario digita outras informações em JTextField’s e JCombox e através de um botão salvar registro tudo no banco.

V

Mas, e cadê suas classes de negócio? Onde está sua classe Produto?
Você não está dividindo sua aplicação em camadas?

Desse jeito, você está misturando banco, negócio e tela.

R

Grato pela paciencia…

Avalie a situação, por favor.

Tenho a classe Conexao, nela estão os métodos para conectar o banco e suas ações.

Tenho a classe Produto, nela estão os getter and setter das variáveis que vou usar nas classes ProdutoTableModel e NovaEntradaDeVenda.

Na ProdutoTableModel, estão os métodos necessários para as ações na classe NovaEntradaDeVenda, utilizando as variáveis de da classe Produto.

Tenho a classe NovaEntrada, nela está a parte visual.

Estou entendo isso direito!?

V

Funciona assim. Você deve dividir sua aplicação em camadas de responsabilidade.

A camada mais básica é a de acesso a dados. Ela basicamente pega dados da sua camada de negócio e salva no banco, e lê do banco transformando esses dados novamente em classes de negócio. Quem usa a camada de dados, não precisa ter idéia de que banco é usado.

Em seguida, vem a camada de objetos de negócio. Ela encapsula todas as regras da sua aplicação. Você terá aqui classes como Produto, Venda, Vendedor, etc…

Finalmente, vem a camada de interface gráfica. Ela faz uso das duas últimas para exibir dados. Ela nunca conversa diretamente com o banco de dados. É um erro de modelagem abrir um resultset diretamente numa tela. O ideal é a tela requisitar produtos à camada de dados (através do DAO) e exibi-los de alguma forma (TableModel).

Espero que tenha ficado mais claro.

R

Minha intenção é essa que citou.

Devo rever a questão de abrir um resultset diretamente numa tela. Mas com estrutura que estou, como devo fazer para enquadrar meu sistema nessa sua citação.

Confesso que entendi mas não compreendi a estrura que deve ser implementação para o Padrão de Projeto DAO. Estou navegando pelo forum pela web em busca de mais esclarecimentos.

Ficarei muito agradecido com sua colaboração, assim como estou.

ViniGody… Valeu mesmo brow, está sendo de grande valia sua contribuição.

Renato Yury.

Criado 12 de junho de 2011
Ultima resposta 13 de jun. de 2011
Respostas 12
Participantes 2