Change background color of one cell in JTable

48,577

You'll need a custom renderer to display the green color when a cell is marked modified in your model.

You'll also need a custom editor to set the model's modified state in your implementation of stopCellEditing(), mentioned here.

A related example of a custom renderer and editor is shown here.

Addendum: Here's an example of the approach described.

inage

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;

/**
 * @see https://stackoverflow.com/a/12352838/230513
 */
public class ModifiedCells extends JPanel {

    public ModifiedCells() {
        final MyModel model = new MyModel();
        JTable table = new JTable(model);
        table.setDefaultRenderer(String.class, new MyRenderer());
        table.setDefaultEditor(String.class, new MyEditor(table));
        this.add(table);
    }

    private static class MyRenderer extends DefaultTableCellRenderer {

        Color backgroundColor = getBackground();

        @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);
            MyModel model = (MyModel) table.getModel();
            if (model.getState(row)) {
                c.setBackground(Color.green.darker());
            } else if (!isSelected) {
                c.setBackground(backgroundColor);
            }
            return c;
        }
    }

    private static class MyEditor extends DefaultCellEditor {

        private JTable table;
        private MyModel model;

        public MyEditor(JTable table) {
            super(new JTextField());
            this.table = table;
            this.model = (MyModel) table.getModel();
        }

        @Override
        public boolean stopCellEditing() {
            model.setState(table.getEditingRow(), true);
            return super.stopCellEditing();
        }
    }

    private static class MyModel extends AbstractTableModel {

        private final List<Row> list = new ArrayList<Row>();

        public MyModel() {
            list.add(new Row("One", true));
            list.add(new Row("Two", false));
            list.add(new Row("Three", false));
        }

        public boolean getState(int row) {
            return list.get(row).state.booleanValue();
        }

        public void setState(int row, boolean state) {
            list.get(row).state = state;
        }

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

        @Override
        public int getColumnCount() {
            return 1;
        }

        @Override
        public Object getValueAt(int row, int col) {
            return list.get(row).name;
        }

        @Override
        public void setValueAt(Object aValue, int row, int col) {
            list.get(row).name = (String) aValue;
            fireTableCellUpdated(row, col);
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        private static class Row {

            private String name;
            private Boolean state;

            public Row(String name, Boolean state) {
                this.name = name;
                this.state = state;
            }
        }
    }

    private void display() {
        JFrame f = new JFrame("ModifiedCells");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ModifiedCells().display();
            }
        });
    }
}
Share:
48,577
Matteo Codogno
Author by

Matteo Codogno

I'm Technical Leader at WellD, a software house delivering innovative solutions in the domains of Energy, Industry automation and Health. I love to experiment with new technologies, open source projects and design Software architectures (I am a kid in a candy store!).

Updated on December 08, 2020

Comments

  • Matteo Codogno
    Matteo Codogno over 3 years

    Possible Duplicate:
    Changing Swing JTable Cell Colors

    I have developed a swing application which shows a JTable. I want that when the user modify a cell value, the cell modified change color.

    This is the code that I run when the user modify a cell:

    this.myTable.getColumnModel().getColumn(column).setCellRenderer(new StatusColumnCellRenderer()); 
    

    And this is the code of my cell Render class:

    public class StatusColumnCellRenderer extends DefaultTableCellRenderer {
    
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
    
            //Cells are by default rendered as a JLabel.
            JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
    
            //Get the status for the current row.
            TableModelLotti tableModel = (TableModelLotti) table.getModel();
    
            if(isSelected)
                l.setBackground(Color.GREEN);
    
            //Return the JLabel which renders the cell.
            return l;
        }
    }
    
    • trashgod
      trashgod almost 12 years
      when the user modifies a cell value: You'll have to maintain this state in your (unseen) TableModel.
    • Matteo Codogno
      Matteo Codogno almost 12 years
      @trashgod Color cell is not related to table model but is related to cellRender.
    • trashgod
      trashgod almost 12 years
      The cell's state goes in the TableModel; it's resulting color is applied in the renderer.
    • Matteo Codogno
      Matteo Codogno almost 12 years
      @Vinesh - I have just look this answer, but not solve my problem! I want that cell color change after the user modify cell value, and the cell must maintain this color!
    • Matteo Codogno
      Matteo Codogno almost 12 years
      @trashgod - can you show me how to do?
    • kleopatra
      kleopatra almost 12 years
      are you sure that you really want to track direct user changes (via editing) to the data? Typically in a load/save data context it doesn't really matter were the change originated (direct edit, progammatic change, indirect user action, wheather change ... :-), as long as the changed data is saved.
  • kleopatra
    kleopatra almost 12 years
    hmm .. a bit on the borderline: a) typically a cellEditor must not change the model (alleviated here because the state is not really a model-property, which is another borderline story :-) b) should call super before changing the state (because it shouldn't if super returned false
  • trashgod
    trashgod almost 12 years
    @kleopatra: I was hoping for your insight; thank you. a) I agree about the CellEditor; it should be a Row.class editor, not String.class; it'll experiment. b) super invokes delegate.stopCellEditing(), which unconditionally returns true after fireEditingStopped(), which invalidates table.getEditingRow().
  • kleopatra
    kleopatra almost 12 years
    ahh (or better beeee :-).. good point! But then, super class behaviour is an implementation detail not to be relied on. A way out (to prevent setting the state in case super refused to stop), grab the editingRow before, message super, and set the state (or not) after.