Salve galera
Seguinte, estou tentado ainda sem sucesso implementar um TableCellRenderer para pintar as linhas conforme um valor. No caso para Clientes, caso o cliente esteja com o status “A” pinta de verde, caso not pinta de vermelho.
Estou tentando assim.
//POJO
public class Clientes{
private Long id;
private String nome;
private String status;
//get e set
}
//AbstractTableModel
public class ClientesTableModel extends AbstractTableModels{
//aqui meus metodos de AbstractTableModel
}
// Renderer
public class ClientesTableCellRenderer extends JLabel implements TableCellRenderer{
public Component getClientesTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Clientes cli = (Clientes)value;
if(cli.getStatus().equals("A"){
setBackground(Color.GREEN);
}else{
setBackground(Color.RED);
}
return this;
}
}
//JDialog
public class Clientes extends JDialog{
JTable tabela = new JTable();
List<Clientes> lista = new ClientesDAO().getAllClientes();
ClientesTableModel model = new ClientesTableModel(lista);
tabela.setModel(model);
tabela.setDefaultRenderer(Object.class, new ClientesTableCellRenderer());
}
Como resolver isso ?
obrigado
[quote=eduJava]alguns desses topicos deve ter a resposta
http://www.guj.com.br/java/124963-jtable-dinamica/3
http://www.guj.com.br/java/236764-como-pintar-o-bakground-de-uma-row-de-uma-jtable-resolvido
http://www.guj.com.br/java/55403-jlabel-no-jtable
http://www.guj.com.br/java/55314-jtable--void-paintimmediately#292964[/quote]
Eu ja havia visto esses links, inclusive eu tenho um modelo aqui em que uso DefaultTableCellRenderer. Mas não sei pq cargas d’agua não estou conseguindo fazer funcionar.
O problema agora é que quando consigo pintar as linhas, os valores não são exibidos.
aqui como estou tentando, agora.
//POJO
public class Clientes{
private Long id;
private String nome;
private String status;
//get e set
}
//ClientesDAO
public List<Clientes> getAllClientes(){
List<Clientes> lista = new ArrayList<Clientes>();
PreparedStatement stm = con.prepareStatement("SELECT * FROM clientes");
ResultSet rs = stm.executeQuery();
while(rs.next()){
Clientes c = new Clientes();
c.setId(rs.getLong("id"));
c.setNome(rs.getString("nome"));
c.setStatus(rs.getString("status"))
lista.add(c);
}
}
//AbstractTableModel
public class ClientesTableModel extends AbstractTableModels{
//aqui meus metodos de AbstractTableModel
}
// TableCellRenderer
public class ClientesTableCellRenderer extends JLabel implements TableCellRenderer{
public Component getClientesTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Clientes cli = (Clientes)value;
if(cli.getStatus().equals("A"){
setBackground(Color.GREEN);
}else{
setBackground(Color.RED);
}
return this;
}
}
//JDialog
public class Clientes extends JDialog{
JTable tabela = new JTable();
List<Clientes> lista = new ClientesDAO().getAllClientes();
ClientesTableModel model = new ClientesTableModel(lista);
tabela.setModel(model);
tabela.setDefaultRenderer(Object.class, new ClientesTableCellRenderer());
}
Alguma sugestão ?
obrigado
cara me parece que vc está colocando um label dentro com cor, mais nao tem o value
tenta algo assim depois de setar a cor
[quote=eduJava]cara me parece que vc está colocando um label dentro com cor, mais nao tem o value
tenta algo assim depois de setar a cor
Não resolveu…
O que preciso é testar se o Cliente estiver com status “A”, pinta de verde, senão pinta de vermelho.
t+ e obrigado
entao vc disse
O problema agora é que quando consigo pintar as linhas, os valores não são exibidos.
vc esta passando um jlabel no seu renderer e vc só esta setando o background
Clientes cli = (Clientes)value;
if(cli.getStatus().equals("A"){
setBackground(Color.GREEN);
}else{
setBackground(Color.RED);
}
setText("aparece isso?");
return this;
cara fiz um teste aqui, meu value não é objeto igual o seu, mais…
[code]
class TabelaRender implements TableCellRenderer{
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JPanel panel = new JPanel(new GridLayout(1,0));
if(table.getValueAt(row, 2).equals("A")){
panel.setBackground(Color.white);
}else{
panel.setBackground(Color.black);
}
JLabel jlabel = new JLabel(value.toString());
jlabel.setForeground(Color.blue);
panel.add(jlabel);
return panel;
}
}[/code]
[quote=eduJava]cara fiz um teste aqui, meu value não é objeto igual o seu, mais…
[code]
class TabelaRender implements TableCellRenderer{
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JPanel panel = new JPanel(new GridLayout(1,0));
if(table.getValueAt(row, 2).equals("A")){
panel.setBackground(Color.white);
}else{
panel.setBackground(Color.black);
}
JLabel jlabel = new JLabel(value.toString());
jlabel.setForeground(Color.blue);
panel.add(jlabel);
return panel;
}
}[/code][/quote]
O erro q esta acontecendo agora é no meu Cast…
Aqui o erro:
java.lang.ClassCastException: java.lang.String cannot be cast to ibg.yanoffice.beans.Clientes
//acontece nesta linha do TableCellRenderer
Clientes cli = (Clientes)value;
hehe
é String e não Cliente por isso não converte
cara copia minha classe TabelaRender e substitui a sua
senão funcionar (teste), vc vai debugando e vendo o erro
[quote=eduJava]hehe
é String e não Cliente por isso não converte
cara copia minha classe TabelaRender e substitui a sua
senão funcionar (teste), vc vai debugando e vendo o erro[/quote]
Sim, é o cast, mas como estou passando o Objeto Cliente, o value deveria recebe-lo não ? Para q assim eu consiga trabalhar com seus métodos.
obrigado.
[quote=fernandopaiva][
Sim, é o cast, mas como estou passando o Objeto Cliente, o value deveria recebe-lo não ? Para q assim eu consiga trabalhar com seus métodos.
[/quote]
Depende. Como é que você definiu seu TableModel?
[quote=entanglement][quote=fernandopaiva][
Sim, é o cast, mas como estou passando o Objeto Cliente, o value deveria recebe-lo não ? Para q assim eu consiga trabalhar com seus métodos.
[/quote]
Depende. Como é que você definiu seu TableModel? [/quote]
Aqui esta como foi definido meu AbstractTableModel
public class ClientesTableModel extends AbstractTableModel{
private List<Clientes> lista;
private String[] colunas = {"Id", "Nome", "Status"};
public ClientesTableModel(){
lista = new ArrayList<Clientes>();
}
public ClientesTableModel(List<Clientes> lista){
this();
this.lista.addAll(lista);
}
@Override
public int getRowCount() {
return lista.size();
}
@Override
public int getColumnCount() {
return colunas.length;
}
public String getColumnName(int column) {
if(colunas[column] == "Id"){
return "Id";
}else if(colunas[column] == "Nome"){
return "Nome";
}else if(colunas[column] == "Status"){
return "Status";
}
return "";
}
public Class getColumnClass(int columnIndex) {
if(colunas[columnIndex] == "Id"){
return long.class;
}else if(colunas[columnIndex] == "Nome"){
return String.class;
}else if(colunas[columnIndex] == "Status"){
return String.class;
}
return Object.class;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Clientes c = lista.get(rowIndex);
switch(columnIndex){
case 0: return new FormataCodigos().retornaCodigoFormatado(r.getId());
case 1: return c.getNome();
case 2: return c.getStatus();
default: return new String();
}
}
public Clientes getClientes(int row){
return lista.get(row);
}
public List<Clientes> getListaClientes(){
return lista;
}
public void alterList(List<Clientes> lista){
this.lista = lista;
fireTableDataChanged();
}
}
vlw, obrigado !
Ou seja, seu TableCellRenderer recebe sempre uma String, porque ela é usada para as colunas 0, 1 e 2. Pense mais ou menos assim: quando o Java precisa desenhar uma célula, ele chama getValueAt, e ele retorna um objeto. Então ele chama o método getTableCellRendererComponent e passa esse objeto para ser mostrado. Só que pelo que você escreveu aí, o tipo do objeto é sempre String.
Se precisar obter o objeto do tipo Clientes, você precisa pegar o parâmetro “row” que é passado para getTableCellRendererComponent, para achar na lista de Clientes qual é o cliente que corresponde a essa linha. OK?
[quote=entanglement][quote]
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Clientes c = lista.get(rowIndex);
switch(columnIndex){
case 0: return new FormataCodigos().retornaCodigoFormatado(r.getId());
case 1: return c.getNome();
case 2: return c.getStatus();
default: return new String();
}
}
[/quote]
Ou seja, seu TableCellRenderer recebe sempre uma String, porque ela é usada para as colunas 0, 1 e 2. Pense mais ou menos assim: quando o Java precisa desenhar uma célula, ele chama getValueAt, e ele retorna um objeto. Então ele chama o método getTableCellRendererComponent e passa esse objeto para ser mostrado. Só que pelo que você escreveu aí, o tipo do objeto é sempre String.
Se precisar obter o objeto do tipo Clientes, você precisa pegar o parâmetro “row” que é passado para getTableCellRendererComponent, para achar na lista de Clientes qual é o cliente que corresponde a essa linha. OK?
[/quote]
Opa, estou passando o List para o TableCellRenderer, veja.
// TableCellRenderer
public class ClientesTableCellRenderer extends JLabel implements TableCellRenderer{
private List<Clientes> lista;
public ClientesTableCellRenderer(List<Clientes> lista){
this.lista = lista;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Clientes c = lista.get(row);
if(c.getStatus().equals("S")){
setBackground(Color.YELLOW);
}else if(c.getStatus().equals("N")){
setBackground(Color.RED);
}
return this;
}
}
// JDialog
public class Clientes extends JDialog{
List<Clientes> lista = new ClientesDAO().getAllClientes();
clientesTableModel = new ClientesTableModel(lista);
tabela.setModel(clientesTableModel);
tabela.setDefaultRenderer(Object.class, new ClientesTableCellRenderer(lista));
}
Obrigado.
Mesmo assim não funciona pintar as linhas necessárias, affs !!!
JTable no Java é tenso d++…é um dos componentes mais tensos de mexer q eu acho.
Qquer sugestão, posta ae !
obrigado.
Antes tarde do que nunca, afinal de contas mais alguém pode chegar aqui e não obter a resposta.
O JTable vai no Modelo para saber que tipo de renderizador irá utilizar logo em:
public Class getColumnClass(int columnIndex) {
if(colunas[columnIndex] == "Id"){
return long.class;
}else if(colunas[columnIndex] == "Nome"){
return String.class;
}else if(colunas[columnIndex] == "Status"){
return String.class;
}
return Object.class;
}
Você especifica o tipo de renderizador vai utilizar para cada coluna, ele simplesmente ignora o tipo de Objeto realmente passado e usa o tipo de coluna, no seu caso você ta passando String.class para as colunas “Id”, “Nome” e “Status”,
logo, faça assim:
public Class getColumnClass(int columnIndex) {
if(colunas[columnIndex] == "Id"){
return Clientes.class;
}else if(colunas[columnIndex] == "Nome"){
return Clientes.class;
}else if(colunas[columnIndex] == "Status"){
return Clientes.class;
}
return Object.class;
}
E …
// TableCellRenderer
public class ClientesTableCellRenderer extends JLabel implements TableCellRenderer{
public Component getClientesTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Clientes cli = (Clientes)value;
if(cli.getStatus().equals("A"){
setBackground(Color.GREEN);
}else{
setBackground(Color.RED);
}
if(colunas[columnIndex] == "Id"){
setText(cli.getId());
}else if(colunas[columnIndex] == "Nome"){
setText(cli.getNome());
}else if(colunas[columnIndex] == "Status"){
setText(cli.getStatus());
}
return this;
}
}
Particularmente, acho que eu construiria um render padrão com comportamentos da linha, e depois estenderia ele sobrescrevendo o método getClientesTableCellRendererComponent para cada coluna.