简体   繁体   中英

How do I to paint a specific column with different colors in JTable?

I have a JTable and I want to paint a column with different colors depending value of cell. To make it I am trying to create a ´TableCellRender´ but cannot make it works, the values seems hidding after ´setDefaultRenderer´.

How could I do it works ?

trying

TableModel

public class PartidasTableModel extends AbstractTableModel{
    private List<Partida> lista;
    private String[] colunas = {"Data ", "Casa x Visitante ", "Banca Inicial ", "Banca Final ", "Saldo ",  "Green/Red "};
    private ControlaDatas cDatas = new ControlaDatas(); 


    public PartidasTableModel(){
       this.lista = new ArrayList<Partida>();
    }

    public PartidasTableModel(List<Partida> lista){
        this();
        this.lista.addAll(lista);
    }

    @Override
    public int getRowCount() {
        return this.lista.size();
    }

    @Override
    public int getColumnCount() {
        return this.colunas.length;
    }

    //private String[] colunas = {"Data ", "Casa x Visitante ", "Banca Inicial ", "Banca Final ", "Saldo ",  "Green/Red "};
    public String getColumnName(int column){
        if(colunas[column] == "Data "){
            return "Data ";
        }else if(colunas[column] == "Casa x Visitante "){
            return "Casa x Visitante ";
        }else if(colunas[column] == "Banca Inicial "){
            return "Banca Inicial ";
        }else if(colunas[column] == "Banca Final "){
            return "Banca Final ";
        }else if(colunas[column] == "Saldo "){
            return "Saldo ";
        }else if(colunas[column] == "Green/Red "){
            return "Green/Red ";
        }
        return "";
    }

    //private String[] colunas = {"Data ", "Casa x Visitante ", "Banca Inicial ", "Banca Final ", "Saldo ",  "Green/Red "};
    public Class getColumnClass(int column){
        if(colunas[column] == "Data "){
            return String.class;
        }if(colunas[column] == "Casa x Visitante "){
            return String.class;
        }else if(colunas[column] == "Banca Inicial "){
            return String.class;
        }else if(colunas[column] == "Banca Final "){
            return String.class;
        }else if(colunas[column] == "Saldo "){
            return String.class;
        }else if(colunas[column] == "Green/Red "){
            return String.class;
        }
        return String.class;
    }

    //private String[] colunas = {"Conta ", "Vencto. ", "Capital R$ ", "Juros R$ "};
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Partida e = (Partida)lista.get(rowIndex);
        switch(columnIndex){
            case 0: return cDatas.getDataFormatada(e.getDtLancamento());
            case 1: return e.getTimeCasa() + " x " + e.getTimeVisitante();
            case 2: return FormataValorMonetario.getValorFormatado(e.getValorInicialBanca()); 
            case 3: return FormataValorMonetario.getValorFormatado(e.getValorFinalBanca()); 
            case 4: return FormataValorMonetario.getValorFormatado(e.getSaldo());  
            case 5: return isGreenOrRed(e.getGreenRed());
            default: return new String();
        }
    }

    private String isGreenOrRed(int value){
        if(value == 1){
            return "GREEN";
        }
        if (value == 2){
            return "RED";
        }
        return "";
    }

    /** retorna o objeto */
    public Partida getObject(int row){
        return lista.get(row);
    }

    /** remove registro da tabela */
    public void removeRow(int row){
        this.lista.remove(row);
        fireTableDataChanged();
    }

    /** altera a tabela */
    public void changeTabela(List<Partida> novaLista){
        this.lista = novaLista;
        fireTableDataChanged();
    }

}

TableCellRenderer

public class PartidaCustomRenderer implements TableCellRenderer{
    private JLabel label;

    public PartidaCustomRenderer() {
        label = new JLabel();
        label.setOpaque(true);
    }



    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

        Object obj = table.getValueAt(row, 5);//
        String redGreen = (String)obj;
        //pinta red/green        
        if(column == 5 && redGreen == "RED"){                      
            label.setBackground(Color.red);
        }else if(column == 5 && redGreen == "GREEN"){
            label.setBackground(Color.green);
        }



        return label;
    }

    private int getAlinhamento(int coluna){
        switch (coluna) {  
           case 0:  
               return SwingConstants.CENTER;  
           case 1:  
               return SwingConstants.LEFT;  
           case 2:  
           default:  
               return SwingConstants.RIGHT;  
       }  
    }
}

Using

public class ViewPartidas extends javax.swing.JDialog {
    private PartidaDAO dao = new PartidaDAO();
    private List<Partida> lista = new ArrayList<Partida>();
    private PartidasTableModel model;

    public ViewPartidas(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
        init();
    }

     private void init(){
        //table  
        lista = dao.findAll(Partida.FIND_ALL, Partida.class);
        model = new PartidasTableModel(lista);
        tabela.setModel(model); 
        tabela.setDefaultRenderer(Object.class, new PartidaCustomRenderer());
        tabela.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        tabela.setAutoCreateColumnsFromModel(false); 
        tabela.getTableHeader().setFont(new Font("Tahoma" , Font.BOLD, 11));
        tabela.getTableHeader().setReorderingAllowed(false);  
        tabela.setFont(new Font("Tahoma", Font.BOLD, 10));

    }

}

Since your renderer is now acting as the default render for all the columns, you need to take into consideration how to handle them as well...

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

    Object obj = table.getValueAt(row, 5);//
    String redGreen = (String)obj;
    //pinta red/green        
    if(column == 5 && redGreen == "RED"){                      
        label.setBackground(Color.red);
    }else if(column == 5 && redGreen == "GREEN"){
        label.setBackground(Color.green);
    }
    // No default fall through functionality
    // for the other columns


    return label;
}

This is complicated to achieve successfully. A better solution would be to set the render to the column you want to use it on...

tabela.getColumnModel().getColumn(5).setCellRenderer(new PartidaCustomRenderer());

I would also recommend using DefaultTableCellRenderer as it is optimised for JTable and is based on JLabel

public class PartidaCustomRenderer extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

        super.getTableCellRendererComponent(table, null, isSelected, hasFocus, row, column);

        String text = (String)value;
        if (column == 5 && text.equals("RED")) {
            setBackground(Color.red);
        } else if (column == 5 && text.equals("GREEN")) {
            setBackground(Color.green);
        }

        return this;
    }

    private int getAlinhamento(int coluna) {
        switch (coluna) {
            case 0:
                return SwingConstants.CENTER;
            case 1:
                return SwingConstants.LEFT;
            case 2:
            default:
                return SwingConstants.RIGHT;
        }
    }
}

From this tutorial:

https://tips4java.wordpress.com/2010/01/24/table-row-rendering/

We get this code:

JTable table = new JTable( model ) {
  public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
    Component c = super.prepareRenderer(renderer, row, column);

    //  Alternate row color
    if (!isRowSelected(row)) {
      c.setBackground(row % 2 == 0 ? getBackground() : Color.LIGHT_GRAY);
    }
    return c;
  }
};

Which should be easy to adapt to columns instead of rows, or a particular column instead of alternating columns.

So to break this down, you're making your own subclass of JTable, and then overriding the prepareRenderer method. You still delegate to the superclass' implementation, but then you take the component it gave you and make specific changes based on the row and column.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM