1

I use Netbeans to develop a java application, I have a result set from MYSQL database and i want to put this data in a JTable. I have a problem when I want to change background color of a JTable cell based on its value (ex: if the value of a cell in Jtable isn't equal to 1, its color must be red). Here is my code:

    /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * 
 */
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.sql.*;
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

public class Cell2 {

    // JDBC driver name and database URL
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://localhost/db";

    //  Database credentials
    static final String USER = "root";
    static final String PASS = "(abdc)";

    public void queryABTS(JTable table) {
        Connection conn = null;
        Statement stmt = null;
        try {
            //STEP 2: Register JDBC driver
            Class.forName("com.mysql.jdbc.Driver");

            //STEP 3: Open a connection
            System.out.println("Connecting to database...");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);

            //STEP 4: Execute a query
            System.out.println("Creating statement...");
            stmt = conn.createStatement();
            String sql;
            sql = "SELECT * from dbn;";
            ResultSet rs = stmt.executeQuery(sql);
            ResultSetMetaData rsmt = rs.getMetaData();
            int c = rsmt.getColumnCount();
            Vector column = new Vector(c);
            for (int i = 1; i <= c; i++) {
                column.add(rsmt.getColumnName(i));
            }
            Vector data = new Vector();
            Vector row = new Vector();
            while (rs.next()) {
                row = new Vector(c);
                for (int i = 1; i <= c; i++) {
                    row.add(rs.getString(i));
                }
                data.add(row);
            }

            table.setModel(new javax.swing.table.DefaultTableModel(data, column));
            table.getTableHeader().setFont(new Font("SansSerif", Font.BOLD, 13));
           // table.getValueAt(1, 1);

            TableColumn column1 = null;

            for (int i = 0; i < 5; i++) {
                column1 = table.getColumnModel().getColumn(i);
                if (i == 3) {
                    column1.setPreferredWidth(150); //third column is bigger

                } else {
                    column1.setPreferredWidth(50);

                }
            }

            setCellRenderer(table);
            //color cell =======================================================================

             // end color cell ==================================================================


//========================================================

//=======================================================
            //STEP 6: Clean-up environment
            rs.close();
            stmt.close();
            conn.close();
        } catch (SQLException se) {
            //Handle errors for JDBC
            se.printStackTrace();
        } catch (Exception e) {
            //Handle errors for Class.forName
            e.printStackTrace();
        } finally {
            //finally block used to close resources
            try {
                if (stmt != null) {
                    stmt.close();
                }
            } catch (SQLException se2) {
            }// nothing we can do
            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException se) {
                se.printStackTrace();
            }//end finally try
        }//end try
        System.out.println("Goodbye!");
    }//end main  


public static TableCellRenderer createCellRenderer() {
    return new DefaultTableCellRenderer() {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component c =  super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            if (column == 4 && "1".equals((String) value)) {
    c.setBackground(Color.RED);
    }

            return c;
        }
    };
}

public static void setCellRenderer(JTable table) {
    TableCellRenderer cellRenderer = createCellRenderer();
    table.setDefaultRenderer(Object.class, cellRenderer);
}





}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Imii Iik
  • 205
  • 1
  • 4
  • 14
  • Have a look at the [JTable](https://docs.oracle.com/javase/tutorial/uiswing/components/table.html) tutorials, in particular the section on custom cell renderers. The basic idea is you need to store enough information with your model so you can make decisions about how to format the data in the renderer, even if that data isn't displayed directly – MadProgrammer Jan 30 '16 at 22:34

2 Answers2

1

Try this

public static TableCellRenderer createCellRenderer() {
    return new DefaultTableCellRenderer() {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component c =  super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            c.setBackground(Color.GREEN);

            return c;
        }
    };
}

public static void setCellRenderer(JTable table) {
    TableCellRenderer cellRenderer = createCellRenderer();
    table.setDefaultRenderer(Object.class, cellRenderer);
}

By calling table.setModel(new javax.swing.table.DefaultTableModel(data, column)); you are putting your data into the table model. JTable uses by default DefaultTableCellRenderer instance to render cells, which can be replaced by your own cell renderer by calling table.setDefaultRenderer(Integer.class, cellRenderer) - this will set custom cellrenderer to all Integer columns (DefaultTableModel uses Object columns). When table is being displayed, each cell of the table is customized by getTableCellRendererComponent(...) method of the table's cellrenderer. In this method, you have current component (cell) with it's value and position (see parameters), that you can use to customize your cell before getting rendered.

So if you want to set background color to RED for each cell in second column with value 1, you would write:

if (column == 1 && ((Integer) value) == 1) {
    c.setBackground(Color.RED);
}

Passing table's data to cell renderer

public static TableCellRenderer createCellRenderer(final Vector data) {
    return new DefaultTableCellRenderer() {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        Component c =  super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            // use data to customize current component

            return c;
        }
    };
}

public static void setCellRenderer(JTable table, Vector data) {
    // Vector data = ((DefaultTableModel) table.getModel()).getDataVector();
    TableCellRenderer cellRenderer = createCellRenderer(data);
    table.setDefaultRenderer(Object.class, cellRenderer);
}
matoni
  • 2,479
  • 21
  • 39
  • I am using a resualtset from mysql, were can I specify the column and all the cell that have value 1 in the second column. Thanks – Imii Iik Jan 30 '16 at 23:16
  • Thanks for your help, I tried this code it doesn't generate errors but the the colors of Jtable cell doesn't change. – Imii Iik Jan 31 '16 at 00:04
  • I forgot, you are using `DefaultTableModel` which uses columns of `Object` type. So you need to set cellrenderer to all "object" columns. Replace `table.setDefaultRenderer(Integer.class, cellRenderer);` by `table.setDefaultRenderer(Object.class, cellRenderer);` – matoni Jan 31 '16 at 00:35
  • Now it works but when I specify that if column 4 equal to 1 , the background color change also for column 5, 6, 7 and 8 (all the rest) and all rows, I changed my question to put update of my code – Imii Iik Jan 31 '16 at 01:05
  • It works now thank you for your help! :-) I add else statement else { c.setBackground(null); } – Imii Iik Jan 31 '16 at 01:14
  • Please I have just another question, if I want to change colors based on value of 2 cells like: if ((column == 5 && "2".equals((String) value)) && (column == 12 && "1".equals((String) value))){ c.setBackground(Color.RED);} – Imii Iik Jan 31 '16 at 01:27
  • Not sure, if you can obtain cell component other than current in cellrenderer, however, you can try to pass your `data` to cell renderer. – matoni Jan 31 '16 at 01:45
0
public class Product extends javax.swing.JPanel {
     
    public Product() {
        initComponents();
         
       getNewRenderedTable(p_table);
       
    }
      
    private static JTable getNewRenderedTable(final JTable table){
        table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer(){
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                
                int status = Integer.parseInt((String) table.getModel().getValueAt(row, 7));
                
                if(status<=5){
                   setBackground(Color.red);
                   setForeground(Color.WHITE);
                }
                else{
                   setBackground(Color.WHITE);
                   setForeground(Color.black);
                }
                return this;
            }
        });
        return table;
    }

}
kelvin
  • 1,421
  • 13
  • 28
pascal
  • 1
  • p_table refers to my jtable name, and status points at the 'quantity' row – pascal May 23 '21 at 18:12
  • 1
    "p_table refers to my jtable name, and status points at the 'quantity' row" Please always make sure to put the context directly in the answer rather than in the comments. Note that you can edit the answer after posting. – kelvin May 23 '21 at 19:01