Retornar objeto de um AbstractTableModel

11 respostas
L
ola boa noite pessoal, sou iniciante no mundo java...e to com um problema em retornar um objeto de um AbstractTableModel ao clicar em um botão. aqui é o formPrincipal
botaoProcurar.addActionListener(new ActionListener() {   
         public void actionPerformed(ActionEvent arg0) {   
  
           listProdutos  rprodutos = new listProdutos();   
                     rprodutos.setVisible(true);   
  
            CadastroProduto produto = new CadastroProduto();   
            produto = rprodutos.getProdutoLinha();   
  
            if (produto != null) {   
  
            txtNomeProduto.setText(String.valueOf(produto   
                     .getNome_produto()));   
            }

A classe ProdutoTableModel , o modelo da tabela.

public ProdutoTableModel() {   
  
      produtos = new CadastroProdutoDAO().lista();   
   }   
  
   public ProdutoTableModel(List<CadastroProduto> lista) {   
      this();   
      produtos.addAll(lista);   
   }   
  
     @Override  
   public Class<?> getColumnClass(int coluna) {         
    return String.class;   
   }   
  
   @Override  
   public int getColumnCount() {   
         return 4;   
   }     
   @Override  
   public String getColumnName(int coluna) {   
            switch (coluna) {   
      case 0:   
         return "CÓDIGO"; colun   
      case 1:   
         return "NOME";    
      case 2:   
         return "VALOR $";      
       case 3:   
         return "ESTOQUE";      
       default:   
         return "";    
      }   
   }   
  
   @Override  
   public int getRowCount() {   
         
            return produtos.size();   
   }   
  
   @Override  
   public Object getValueAt(int linha, int coluna) {   
         
            CadastroProduto c = produtos.get(linha);   
            switch (coluna) {   
      case 0:   
         return c.getIdcadastroProduto();   
      case 1:   
         return c.getNome_produto();   
      case 2:   
         return c.getValor_venda();    
      case 3:   
         return c.getEstoque();     
      default:   
         return null;       }   
   }   
  
   @Override  
   public boolean isCellEditable(int rowIndex, int columnIndex) {   
      return false;   
   }   
  
   public void adiciona(CadastroProduto c) {   
      produtos.add(c);   
         
      fireTableRowsInserted(produtos.size() - 1, produtos.size() - 1);   
   }   
  
   public int getIndice(CadastroProduto c) {   
      return produtos.indexOf(c);   
   }   
  
   public void adicionaLista(List<CadastroProduto> lista) {   
      int i = produtos.size();   
      produtos.addAll(lista);   
      fireTableRowsInserted(i, i + lista.size());   
   }   
  
   public CadastroProduto getCadastroProduto(int linha) {   
      return produtos.get(linha);   
   }

e a classe que popula a tabela

public void instanciaComponentes() {
		modelo = new ProdutoTableModel();
		modelo.addTableModelListener(this);
		tabela = new JTable();
		tabela.setModel(modelo);
		tabela.setVisible(true);
		scrollPane = new JScrollPane();
		scrollPane.setViewportView(tabela);

		botaoAdicionar = new JButton();
		botaoAdicionar.setText("Adicionar");
		botaoAdicionar.addActionListener(new ActionListener() {
			        @Override  
         public void actionPerformed(ActionEvent e) {   
  
            int indice = tabela.getSelectedRow();   
            CadastroProduto prod = modelo.getCadastroProduto(indice);   
            produto = prod;   
            dispose();   
         }   
      });   
}


	public Produto retornaProdutoSelecionado() {
		modelo = (ProdutoTableModel) tabela.getModel();
		return modelo.getCadastroProduto(tabela.getSelectedRow());
	}

	public Produto getProdutoLinha() {
		return produto;

	}

	private void adicionaComponentes() {
		getContentPane().add(scrollPane);
		JPanel panel = new JPanel();
		getContentPane().add(panel, BorderLayout.SOUTH);
		panel.add(botaoAdicionar);

	}

	private void ajustaJanela() {
		setTitle("Produtos Cadastrados");
		pack();
		setLocationRelativeTo(null);
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		setVisible(true);
	}

	@Override
	public void tableChanged(TableModelEvent e) {
		String tipo;
		switch (e.getType()) {
		case TableModelEvent.DELETE:
			tipo = "DELETE";
			break;
		case TableModelEvent.INSERT:
			tipo = "INSERT";
			break;
		case TableModelEvent.UPDATE:
			tipo = "UPDATE";
			break;
		default:
			tipo = "?";
			break;
		}
		System.out.printf("%s: %d-%d, %d%n", tipo, e.getFirstRow(),
				e.getLastRow(), e.getColumn());
	}

me basei em dicas e códigos ja postados aqui no forum. a princípio tabela resgata os dados mas antes de mostrar os dados na tabela ele chama o método do meu formPrincipal [getProdutoLinha();] e gera uma exceção pois ainda n selecionei nenhum item... alguem tem idéia do que seja?
Obrigada

11 Respostas

Nicolas_Fernandes

Já pensou em postar a exceção que está gerando para termos uma ideia melhor do que está acontecendo? :wink:

Nicolas_Fernandes

Normalmente, ao trabalhar com JTables, eu faço assim:

1. Crio minha classe de domínio. Vamos exemplificar com uma classe Aluno:
public class Aluno {

   private String nome;
   private String status;

   // getters e setters omitidos, além do toString() sobrescrito, se quiser, dentre outros.
}
2. Crio uma classe de persistência para essa entidade do Banco de Dados:
public class PersistenciaAluno {

    public List<Aluno> recuperarTodos() throws SQLException {

        Connection connection = GerenciadorConexoes.recuperarConnection();
        String sentencaSelect = "SELECT * FROM DBO.ALUNOS";
        PreparedStatement statementSelect = connection.prepareStatement(sentencaSelect);
        ResultSet resultSelect = statementSelect.executeQuery();
        
        List<Aluno> listAlunos = new ArrayList<Aluno>();
        while (resultSelect.next()) {

            listAlunos.add( this.recuperarObjeto(resultSelect) );
        }

        resultSelect.close();
        return listAlunos;
    }

     public Aluno recuperarObjeto(ResultSet resultSelect) {

         Aluno aluno = new Aluno();
          
         aluno.setNome(resultSelect.getString("NOME"));
         aluno.setStatus(resultSelect.getString("STATUS"));

         return aluno;
     }
}
3. Crio o meu TableModel para essa JTable:
public class AlunoTableModel extends AbstractTableModel {
 
    private List<Aluno> listAlunos;
    private static final int colunaNome = 0;
    private static final int colunaStatus = 1;


    public AlunoTableModel(List<Aluno> listAlunos) {
 
        this.listAlunos = listAlunos != null ? listAlunos : new ArrayList<Aluno>();
    }

    @Override public Class<?> getColumnClass(int coluna) {           
        return String.class;     
    }     
    
    @Override public int getColumnCount() {     
        return 2;     
    }   
    @Override public int getRowCount() {     
        return listAlunos.size();     
    }  
    @Override public boolean isCellEditable(int rowIndex, int columnIndex) {     
        return false;     
    }  

    @Override public String getColumnName(int coluna) {     
            
        if (coluna == colunaNome) return "Nome do aluno";
        if (coluna == colunaStatus) return "Status do aluno"; 

        return "";
    }     

    @Override public Object getValueAt(int linha, int coluna) {     
     
        Aluno aluno = listAlunos.get(linha); 
        if (coluna == colunaNome) return aluno.getNome();
        if (coluna == colunaStatus) return aluno.getStatus(); 

        return "";   
   }    
}
4. Crio minha Interface GUI, juntamente com uma JTable e um objeto que gerenciará o modelo da tabela.
public class InterfaceGerenciamentoAlunos extends JFrame {

    private JTable tableAlunos;
    private JScrollPane scrollTable;
    private AlunosTableModel modeloAlunos;

    public InterfaceGerenciamentoAlunos() {

        try {
 
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelName());
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setResizable = false;

            PersistenciaAluno persistenciaAluno = new PersistenciaAluno();
            List<Aluno> listAlunos = persistenciaAluno.recuperarTodos();
            modeloAlunos = new AlunosTableModel(listAlunos);

            tableAlunos = new JTable(modeloAlunos);
            scrollTable = new JScrollPane(tableAlunos);
 
            this.getContentPane().add(scrollTable);
        }
        catch (ClassNotFoundException errClass) {
            errClass.printStackTrace();
        }
        catch (SQLException errSQL) {
            errSQL.printStackTrace();
        }
        catch (Exception err) {
            err.printStackTrace();
        }
    }

    public void exibirFormulario() {

        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }
}
E, finalmente, faço a chamada da interface no Main:
public class Main {

    public static void main(String[] args) {

        try {

            InterfaceGerenciamentoAlunos interfaceGerenciamentoAlunos = new InterfaceGerenciamentoAlunos();
            interfaceGerenciamentoAlunos.exibirFormulario();
        }
        catch (Exception err) {

            err.printStackTrace();
        }
    }
}

Bom, tá sem arquitetura, sem padrão nenhum e fiz "no olho"... mas é por aí... tenta seguir mais ou menos isso pra ver se resolve seu problema! ;)

L
Olá Nicolas Fernandes, acho que não soube me expressar direito... eu consigo criar a tabela, só que não estou conseguindo retornar para o main o objeto quando clico no botão Adicionar. Quando eu debugo percebi que quando chega
public static void main(String[] args) {
				listProdutos rprodutos = new listProdutos();
				rprodutos.ajustaJanela();

				Produto produto = new Produto();
				produto = rprodutos.retornaProdutoSelecionado();
				}

só após terminar esse código, que os dados aparecem na tabela, ñão to conseguindo saber por que tá acontecendo isso. :S
ps: Agora não gera mais nenhuma exceção, fiz uma alteração de acordo com o seu modelo postado acima.
Obrigada pela Ajuda.

Nicolas_Fernandes
lmqds:
Olá Nicolas Fernandes, acho que não soube me expressar direito... eu consigo criar a tabela, só que não estou conseguindo retornar para o main o objeto quando clico no botão Adicionar. Quando eu debugo percebi que quando chega
public static void main(String[] args) {
				listProdutos rprodutos = new listProdutos();
				rprodutos.ajustaJanela();

				Produto produto = new Produto();
				produto = rprodutos.retornaProdutoSelecionado();
				}

só após terminar esse código, que os dados aparecem na tabela, ñão to conseguindo saber por que tá acontecendo isso. :S
ps: Agora não gera mais nenhuma exceção, fiz uma alteração de acordo com o seu modelo postado acima.
Obrigada pela Ajuda.

Altera esse retornaProdutoSelecionado. Coloque um método que receba um inteiro por parâmetro e retorne o objeto, como tá sendo feito:
// Como parâmetro, você recebe o índice selecionado pelo usuário.
// Esse método só deve ser chamado ao selecionar um registro na tabela.
public Produto retornaProdutoSelecionado(int linha) {  

    modelo = (ProdutoTableModel) tabela.getModel();  
    return modelo.getCadastroProduto(linha);  
}

Além disso, coloque esse código dentro de um evento de um botão no estilo "Pesquisar", ou ao selecionar algum registro na tabela, não solto no código do jeito que está. Do modo que tá no código, você não tem nenhuma linha selecionada; logo, não retornará nenhum objeto.

E porque você quer chamar um método de "retornar" um objeto em um método de "adicionar"? Não faz muito sentido, né? rs

L
eu já tenho um método para selecionar a linha
botaoAdicionar = new JButton();
		botaoAdicionar.setText("Adicionar");
		botaoAdicionar.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int indice = tabela.getSelectedRow();
				Produto prod = modelo.getCadastroProduto(indice);
				produto = prod;
				dispose();
			}
		});

	}
public Produto getProdutoLinha() {
		return produto;

	}

o problema está na hora que instancio a classe, dessa forma :

main
listProdutos rprodutos = new listProdutos();

				rprodutos.ajustaJanela(); // até esse momento o qual deveria aparecer os dados da tabela não mostra nada

				Produto produto = new Produto();
				produto = rprodutos.getProdutoLinha(); //só vem a mostrar os dados da tabela quando encerra esse método aqui...

bom, a minha idéia é assim, eu tenho um frame que cadastro os itens que o cliente consumiu, e para alimentar esse frame com os itens, eu pesquiso no bd os itens cadastrados, que
qdo clicar no add retornar o item escolhido,foi essa a solução que pensei, mas se quiser me sugerir algo mais interessante, fique a vontade.

Nicolas_Fernandes
lmqds:
eu já tenho um método para selecionar a linha
botaoAdicionar = new JButton();
		botaoAdicionar.setText("Adicionar");
		botaoAdicionar.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int indice = tabela.getSelectedRow();
				Produto prod = modelo.getCadastroProduto(indice);
				produto = prod;
				dispose();
			}
		});

	}
public Produto getProdutoLinha() {
		return produto;

	}

o problema está na hora que instancio a classe, dessa forma :

main
listProdutos rprodutos = new listProdutos();

				rprodutos.ajustaJanela(); // até esse momento o qual deveria aparecer os dados da tabela não mostra nada

				Produto produto = new Produto();
				produto = rprodutos.getProdutoLinha(); //só vem a mostrar os dados da tabela quando encerra esse método aqui...

bom, a minha idéia é assim, eu tenho um frame que cadastro os itens que o cliente consumiu, e para alimentar esse frame com os itens, eu pesquiso no bd os itens cadastrados, que
qdo clicar no add retornar o item escolhido,foi essa a solução que pensei, mas se quiser me sugerir algo mais interessante, fique a vontade.


Foi isso que não entendi: porque você seleciona um registro ao cadastrar um novo registro? Não faz muito sentido.
Preencha o seu TableModel na construção do formulário; após isso, você só buscara um item dentro de um método de pesquisa, ou em algum evento da sua JTable ao selecionar uma linha.

Esse listProdutos é uma que tipo de classe? Um frame?
Métodos como o seu ajustaJanela, são chamados somente no final do preenchimento de TODO o formulário. Portanto, chame os seus métodos de preencher componentes, alinhá-los e tudo o mais, e só depois chame o ajustaJanela.

Minha solução:
1. Preencha os valores do modelo no construtor da classe [já exemplifiquei acima];
2. Crie um listener para a JTable para, quando selecionar um registro, aí sim pesquisar esse objeto.

L

alterei meu código como vc falou ficou assim

public class listProdutos extends JFrame {
private JTable tableAlunos;
	private JScrollPane scrollTable;
	private CadastroProdutoTableModel modeloAlunos;
	public Produto produto;

	public listProdutos() {

		try {

			this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			this.setResizable(false);

			CadastroProdutoDAO persistenciaAluno = new CadastroProdutoDAO();
			List<Produto> listAlunos = persistenciaAluno.lista();
			modeloAlunos = new CadastroProdutoTableModel(listAlunos);

			tableAlunos = new JTable(modeloAlunos);
			tableAlunos.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent arg0) {

					int linha = tableAlunos.getSelectedRow();

					produto = new Produto();

					produto.setFornecedor(tableAlunos.getValueAt(linha, 1)
							.toString());
					produto.setNome_produto(tableAlunos.getValueAt(linha, 2)
							.toString());
					produto.setValor_venda(Integer.parseInt(tableAlunos
							.getValueAt(linha, 3).toString()));

				}
			});
			scrollTable = new JScrollPane(tableAlunos);

			this.getContentPane().add(scrollTable);
		} catch (Exception err) {
			err.printStackTrace();
		}
	}

	public void exibirFormulario() {
		this.pack();
		this.setLocationRelativeTo(null);
		this.setVisible(true);
	}

	public Produto getProduto() {
		return produto;
	}

só que continua a mesma coisa, só preenche a tabela quando o main termina de executar…
e gera essa exception

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 2 >= 2
	at java.util.Vector.elementAt(Unknown Source)
	at javax.swing.table.DefaultTableColumnModel.getColumn(Unknown Source)
	at sun.swing.SwingUtilities2.convertColumnIndexToModel(Unknown Source)
	at javax.swing.JTable.convertColumnIndexToModel(Unknown Source)
	at javax.swing.JTable.getValueAt(Unknown Source)
	at br.com.TableModel.listProdutos$1.mouseClicked(listProdutos.java:119)
	at java.awt.AWTEventMulticaster.mouseClicked(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)

to quebrando minha cabeça e n to conseguindo.

Nicolas_Fernandes

Coloca uma condicional IF para verificar se tem linha selecionada!

if (tableAlunos.getSelectedRow() != -1) {
   // faz suas coisas...
}
L

continuaa gerando a mesma exceção…

inclusive continua a mesma forma, só quando acaba o main( o método que invoca o listProduto) que o Jtable é preenchida, mesmo ajustando de acordo com o seu exemplo, alguma sugestão específico para esse erro?

L
tableAlunos.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent arg0) {

					if (tableAlunos.getSelectedRow() != -1) {

						int linha = tableAlunos.getSelectedRow();

						produto = new Produto();

						produto.setFornecedor(tableAlunos.getValueAt(linha, 1)
								.toString());
						produto.setNome_produto(tableAlunos
								.getValueAt(linha, 2).toString());
						produto.setValor_venda(Double.parseDouble(tableAlunos
								.getValueAt(linha, 3).toString()));
						dispose();
					}
				}
			});

seria assim?

L

alguem?

Criado 21 de julho de 2011
Ultima resposta 28 de jul. de 2011
Respostas 11
Participantes 2