Exibir Dados

Olá
Sou iniciante em JAVA, atualmente programo em Delphi, então, pretendo aprender essa linguagem fantástica, porém estou encontrando dificuldades no que se refere a exibir os registros num grid ou tabela, no Delphi é muito simples, mas no JAVA, pra quem não conhece nada, é meio complicadinho…
Então para iniciar os meus estudos criei um banco em MySQL com uma tabela, banco ESTUDO, tabela cliente com dois campos
Tabela Cliente:
Codigo INT
Nome VARCHAR

Gostaria de saber como posso fazer para mostrar os dados dessa tabela dinamicamente, como eu já recebi algumas dicas aqui no próprio fórum, é desaconselhado o uso de DefaultTableModel, então pretendo aprender da forma correta, porém, com os exemplos encontrados, não consegui sair do lugar…

Pretendo fazer essa tabela aparecer através do NetBeans, mas, se for mais eficiente para meu aprendizado, pode ser no JCreator.

Se os colegas de fórum puderem me dar uma luz, ficarei muito agradecido…

Abraço…

http://www.guj.com.br/posts/list/30/147521.java#799170

http://www.guj.com.br/posts/list/132698.java#714736

http://www.guj.com.br/posts/list/225793.java

Eis alguns exemplos comentados.

Pode usar o ObjectTableModel do Marky.Vasconcelos. Mas se não sabe como funciona um table model, é interessante aprender como funciona para depois usar o ObjectTableModel.

Você pode criar a tela no netbeans sem problemas. Mas ao invés de usar o Default, deve setar seu modelo com:

table.setModel(new SeuTableModel());

Olá
Tentei fazer pelo método do primeiro link
http://www.guj.com.br/posts/list/30/147521.java#799170
mas está dando erro na linha do bloco:

public String getColumnName(int columnIndex){ if(columnIndex == CODIGO)return "Código"; if(columnIndex == NOME) return "Nome"; }
dá a mensagem:
missing return statement

o que estaria faltando nesse caso?

Retorne uma string vazia no final.

public String getColumnName(int columnIndex){ if(columnIndex == CODIGO)return "Código"; if(columnIndex == NOME) return "Nome"; return ""; }O que ocorre é o seguinte, se a coluna for a do código, retorna “Código”, se for a do nome, retorna “Nome”, e se não for nenhum deles, não está retornando nada. Por isso que o compilador está reclamando.

Antes de mais nada, obrigado pela atenção Eric.
Bom, aquele erro não ocorre mais, criei 3 arquivos de classes, baseados no exemplo seu que tem disponível no link que você sugeriu, bem, ficou dessa forma:
Arquivo Tabelas.java

[code]import javax.swing.;
import javax.swing.table.TableModel;
import javax.swing.table.AbstractTableModel;
import java.util.List;
import java.util.ArrayList;
import java.util.
;

public class Tabelas extends AbstractTableModel{

private static final int CODIGO = 0;
private static final int NOME = 0;

private List<Cliente>valores;


public Tabelas(Collection<Cliente> valores) {
	this.valores = new ArrayList<Cliente>(valores);
}

public int getRowCount(){
	return valores.size();
}

public int getColumnCount(){
	return 5;
}

public String getColumnName(int columnIndex){
	if(columnIndex == CODIGO)return "Código";
	if(columnIndex == NOME) return "Nome";
	return "";
}

public Object getValueAt(int row, int column){

	Cliente cli = valores.get(row);
	if(column == CODIGO) cli.getCodigo();
	if(column == NOME) cli.getNome();
	return "";
}

public Class getColumnClass(int columnIndex){
	if(columnIndex == CODIGO)return Integer.class;
	if(columnIndex == NOME)return String.class;
	return String.class;
}

public void add(Cliente cliente){
	valores.add(cliente);
	fireTableRowsInserted(valores.size()-1, valores.size()-1);
}

public List<Cliente> getClientes(){
	return Collections.unmodifiableList(valores);
}

}[/code]

Arquivo Cliente.java

[code]public class Cliente {

private Integer codigo;
private String nome;

public Integer getCodigo(){
	return codigo;
}

public void setCodigo(Integer codigo){
	this.codigo = codigo;
}

public String getNome(){
	return nome;
}

public void setNome(String nome){
	this.nome = nome;
}

}[/code]

Arquivo Principal.java -> é neste que pretendo mostrar a tabela:

[code]import java.awt.;
import javax.swing.
;
import java.util.*;

public class Principal extends JFrame {

private JTable tabela;

public Principal() {
	super("Teste de Tabela");
	initialize();
}

private void initialize(){
	setSize(600, 400);
	setDefaultCloseOperation(EXIT_ON_CLOSE);
	getContentPane().add(new JScrollPane(getTbltabela()));
}

private JTable getTbltabela(){
	if(tabela == null){
		tabela = new JTable();
		tabela.setModel(new Tabelas());
	}
	return tabela;
}

private Tabelas getModel(){
	if(model == null){
		model = (Tabelas) getTbltabela().getModel();
	}
	return model;
}

}[/code]

Bom, pretendo pegar os dados do meu banco estudo e da tabela Cliente qe tem 2 campos: codigo e nome, que são feitos em mysql, sem querer ser muito abusado, o que está faltando neste último arquivo, e, qual seria o próximo passo para exibir os dados da minha tabela do banco nesta JTable?
Realmente, não sei como prosseguir neste momento, estou fazendo com o JCreator o meu pequeno Form.
Se for possível, verificar o meu código e dizer o que estou errando ou o que poderia ser melhorado… :smiley:

Abraço…

A única coisa que pode causar um efeito indesejado é o método getColumnCount, que está retornando 5, quando seu cliente tem apenas código e nome. Neste caso o correto é que retorne 2, caso contrário você terá uma tabela com código, nome e mais três colunas vazias.

E por convenção é interessante nomear o TableModel como ClientesTableModel, assim fica claro para qualquer um que veja suas classes, que ela se trata de um table model próprio para clientes. Do jeito que está, não fica claro que a classe Tabelas seja um table model, ainda mais de clientes.

O próximo passo é carregar um objeto do tipo Cliente com as informações do banco de dados e passá-lo para o table model pelo método add do seu table model.

Olá, alterei agora, seguindo a idéia do seu exemplo: http://www.guj.com.br/java/225793-exemplo-de-tablemodel
ficou assim:

[code] import java.awt.;
import javax.swing.
;
import java.util.*;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import java.sql.*;

public class Principal extends JFrame {
private static final long serialVersionUID = 1L;

private JTable tblCliente;
private ClienteTableModel model;


public Principal(){
	super("Teste com JTable");
	initialize();
}

private void initialize(){
	setSize(800, 600);
	setDefaultCloseOperation(EXIT_ON_CLOSE);
	getContentPane().add(new JScrollPane(getTblClientes()));
}

private JTable getTblClientes(){
	if(tblCliente == null){
		tblCliente = new JTable();
		tblCliente.setModel(new ClienteTableModel());
	}
	return tblCliente;
}

private ClienteTableModel getModel(){
	if(model == null){
		model = (ClienteTableModel) getTblClientes().getModel();
	}
	return model;
}

private Cliente getCliente(){
	Cliente cliente = new Cliente();
	cliente.setCodigo(1);
	cliente.setNome("Teste");
	return cliente;
}

private void addCliente(){
	getModel().addCliente(getCliente());
}

public static void main(String[] args){
	EventQueue.invokeLater(new Runnable(){
		@Override
		public void run(){
		new Principal().setVisible(true);
		}
	});
}

}[/code]

Mas, não consegui encontrar uma maneira de fazer um select e jogar para a tabela…e a minha tabelinha de estudos tem apenas dois campos…

[quote=taraciuk]Mas, não consegui encontrar uma maneira de fazer um select e jogar para a tabela…e a minha tabelinha de estudos tem apenas dois campos…
[/quote]
Se você não sabe como fazer a conexão com o banco de dados, faça uma pesquisa sobre JDBC. Aqui no GUJ tem alguns artigos e vários tópicos sobre o assunto: http://www.guj.com.br/articles/7

Se já souber trabalhar com JDBC e o problema está em como carregar os resultado da consulta na JTable. Você pode carregar um objeto Cliente com o resultado da pesquisa e passar para o table model pelo método add, que recebe um cliente.

Edit: Achei um exemplo que carrega um objeto “Usuario” para cada resultado da consulta e retorna uma lista: http://www.guj.com.br/java/225388-coletando-dados-de-um-select#1154746
Se quiser pode até criar um método em seu table model para adicionar a lista de clientes de uma vez só.

E, assim, como eu jogo o resultado do select do exemplo que você citou no último post para a JTable que criei baseado na que vc fez como exemplo ?

Ainda nao consegui me encontrar no código…
Talvez seja o efeito de ter aprendido a programar em Delphi antes…

No seu table model, o responsável por adicionar um cliente na tabela é o método “add(Cliente)”. Então bastaria carregar os dados do banco em um objeto cliente e adicionar ao model por este método.

tableModel.add(clienteRecuperado);

Como a consulta no banco pode retornar vários resultados, você pode implementar um método que recebe uma lista de clientes, para evitar de ficar escrevendo laços para adicioná-los:

// Seu table model public void addAll(List<Cliente> clientes) { int oldSize = getRowCount(); valores.addAll(clientes); fireTableRowsInserted(oldSize, getRowCount() - 1); }Assim pode passar a lista toda para o método addAll.

Cara, acho que estou te enchendo já…rsrssr
Tentei montar seguindo os exemplos, mas não consegui sozinho não.

Se puder me dar uma luz, dizer onde estou errando.

Abraço…

Para facilitar a adição dos clientes no seu table model, crie o método que recebe uma lista:

[quote=Eu mesmo] public void addAll(List<Cliente> clientes) { int oldSize = getRowCount(); valores.addAll(clientes); fireTableRowsInserted(oldSize, getRowCount() - 1); }[/quote]
Em sua classe principal, tem o método “listarClientes”, que retorna uma lista de clientes, que é exatamente o que o método acima recebe por parâmetro. Para passá-los para a tabela, você vai fazer algo mais ou menos assim:

getModel().addAll(listarClientes()); // "getModel" retorna o seu table model, "addAll" vai adicionar ao model a lista de clientes que será retornada pelo método "listarClientes".Onde este método vai ser chamado depende de sua necessidade. Pode ser por exemplo a partir da ação de um botão.

Quanto a conexão, procure fechar o statement e a conexão quando não for usar mais. Você pode criar, também, uma classe para trabalhar com a conexão: http://download.oracle.com/javase/tutorial/jdbc/basics/index.html.

Cara, agora apareceu algo, mas, apareceu somente a primeira linha de dados da tabela, deu a msg:
Comprimento inválido de cadeia de caracteres ou de buffer

Acho que é no while, o que pode ser feito neste caso?

[code]public List listCliente(){
Listlinhas = new ArrayList();

	try{
		String url = "jdbc:odbc:estudo";
		String usuario = "root";
		String senha = "root";
		Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		Connection con;
		con = DriverManager.getConnection(url, usuario, senha);
		Statement st = con.createStatement();
		ResultSet rs = st.executeQuery("Select CodCliente, NomeCliente from Cliente");

		while(rs.next()){
			Cliente cli = new Cliente();
			cli.setCodigo(rs.getInt("CodCliente"));
			cli.setNome(rs.getString("NomeCliente"));
			linhas.add(cli);

		}
	}
		catch(Exception e){
			JOptionPane.showMessageDialog(null,e,"Mensagem",JOptionPane.ERROR_MESSAGE);
		}
		return linhas;
}[/code]

Por esta mensagem não sei te dizer de onde vem o erro. Coloca um printStackTrace no catch para poder ver qual é a exceção.

catch(Exception e){ e.printStackTrace(); JOptionPane.showMessageDialog(null,e,"Mensagem",JOptionPane.ERROR_MESSAGE); }

Na saída do JCreator saiu isso:

[quote]java.sql.SQLException: [Microsoft][ODBC Driver Manager] Comprimento inválido de cadeia de caracteres ou de buffer
at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6957)
at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7114)
at sun.jdbc.odbc.JdbcOdbc.SQLGetDataString(JdbcOdbc.java:3907)
at sun.jdbc.odbc.JdbcOdbcResultSet.getDataString(JdbcOdbcResultSet.java:5698)
at sun.jdbc.odbc.JdbcOdbcResultSet.getString(JdbcOdbcResultSet.java:354)
at sun.jdbc.odbc.JdbcOdbcResultSet.getString(JdbcOdbcResultSet.java:411)
at Principal.listCliente(Principal.java:99)
at Principal.addAll(Principal.java:71)
at Principal.access$000(Principal.java:27)
at Principal$2.actionPerformed(Principal.java:119)
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.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6267)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6032)
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:4577)
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)[/quote]

Era isso ?

Tenta ver o tamanho do campo no BD, pode ser que o registro esteja além dos limites especificados. Apesar que você só está tentando recuperar algo já cadastrado.

Copia a primeira linha do erro e cola no google pra ver se não acha ninguém que teve o mesmo problema.

No Banco o tamanho dos campos é inteiro(10), varchar(45).
Agora, se eu coloco assim:

		while(rs.next()){
			Cliente cli = new Cliente();
			[color=red]Cliente nome = new Cliente();[/color]
			cli.setCodigo(rs.getInt("CodCliente"));
			cli.setNome(rs.getString("NomeCliente"));
			linhas.add(cli);

		}

Adicionando essa linha em vermelho no while, os dados aparecem e não ocorre o erro.
Pesquisando no google, encontrei uma pesquisa exatamente com o meu erro, mas nao mostra a solução, apenas diz que conseguiu resolver:
http://www.guj.com.br/java/221519-formulario-e-sql

Tem idéia do que poderia ser?

Cara, obrigado pela tua paciência e atenção às minhas dúvidas.

Estranho… porque essa linha em vermelho não fez nada demais… Qual BD é esse que estás usando ??? Pela URL não consegui identificar…

Tenta alterar os nomes das Colunas… Ao que tudo indica é infra, teu código está correto…

Sinceramente não sei te dizer qual poderia ser o problema.

E entendi menos ainda porque criar outro cliente na memória e não fazer nada com ele tenha resolvido o problema.

Já tentou debugar o código?

Estou utilizando o MySQL 5
Sim, foi o que imaginei, que esta linha não está fazendo nada no meio do while, mas, se eu tiro ela, apresenta o erro que postei.

java.sql.SQLException: [Microsoft][ODBC Driver Manager] Comprimento inválido de cadeia de caracteres ou de buffer

Levando em conta que o meu banco tem somente uma tabela e com dois campinhos somente…pois estou tentando aprender JAVA.

Estou utilizando o JCreator, pra debugar teria que ser pelo NetBeans?
Comecei pelo JCreator porque achei que o aprendizado se torna mais facil, fazendo tudo na mão, depois, passo a utilizar o NetBeans ou outra IDE.