2

Here's an example Nimbus JTable.

When a checkbox is selected, I want to color its entire row green.

The problem: the green skips every other row, only in the boolean column.

This problem only happens with the Nimbus LaF, which alternates white and gray rows by default. For boolean columns only, it's as if alternating color is being forced no matter what coloring you try to apply. Can this be overriden?

Code that produces the above tables (MCVE):

import java.awt.*;
import javax.swing.*;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.table.*;

public class AlternatingGreenTableTest extends JFrame {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                        if ("Nimbus".equals(info.getName())) {
                            UIManager.setLookAndFeel(info.getClassName());
                            break;
                        }
                    }
                } catch (Exception e) {
                    try {
                        UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
                    } catch (Exception e1) {
                        e1.printStackTrace();
                    } 
                }

                try {
                    AlternatingGreenTableTest frame = new AlternatingGreenTableTest();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public AlternatingGreenTableTest() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        String[] columnNames = {"First Name", "Vegetarian"};

        Object[][] data = {
                {"Kathy", new Boolean(false)},
                {"John", new Boolean(false)},
                {"Sue", new Boolean(false)},
                {"Jane", new Boolean(false)},
                {"Joe", new Boolean(false)},
                {"Bob", new Boolean(false)}
        };

        TableModel model = new DefaultTableModel(data, columnNames) {
            public Class getColumnClass(int c) {

                /* Need this so that Boolean columns render as checkboxes */
                return getValueAt(0, c).getClass();
            }
        };

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

                if (!isRowSelected(row)) {
                    int modelRow = convertRowIndexToModel(row);
                    Boolean isExaminedChecked = (Boolean) getModel().getValueAt(modelRow, 1);
                    if (isExaminedChecked) {

                        /* 'Examined' is checked in the given row, so color the row green. */
                        c.setBackground(Color.GREEN);
                    } else {

                        /* 'Examined' is not checked in the given row, so color the row with one of the default alternating colors. */
                        Color defaultBackgroundColor = (Color) UIManager.get("Table:\"Table.cellRenderer\".background");
                        Color alternatingColor = (Color) UIManager.get("Table.alternateRowColor");
                        c.setBackground(row % 2 == 0 ? defaultBackgroundColor : alternatingColor);
                    }
                }

                return c;
            }
        };

        /* Need this or Boolean column won't turn green at all */
        ((JComponent) table.getDefaultRenderer(Boolean.class)).setOpaque(true);

        getContentPane().add(table);
        pack();
    }
}
Brent
  • 121
  • 2
  • 1
    1. as I mentioned use opacity in the renderer, 2. :-) to delete this question, – mKorbel Oct 09 '15 at 18:58
  • @mKorbel I'm not sure what you mean for the opacity, could you please clarify or say how to actually do that? Also, why delete this question instead of editing it? – Brent Oct 09 '15 at 19:14

1 Answers1

1

based on my deleted post (visible for user with rep. score >10k) in Nimbus and alternate row colors

import java.awt.Color;
import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.ColorUIResource;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

//https://stackoverflow.com/a/12398941/714968
public class TableDemo {

    private static void createAndShowGUI() {
        final JFrame frame = new JFrame("TableDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel contentPanel = new JPanel();
        String[] columnNames = {"Col1", "Col2", "Col3", "Col4", "Col5"};
        Object[][] data = {
            {"1", "3", "2", "4", new Boolean(false)}, {"2", "5", "1", "3", new Boolean(false)},
            {"4", "1", "5", "2", new Boolean(false)}, {"5", "3", "4", "1", new Boolean(false)},
            {"1", "3", "2", "4", new Boolean(false)}, {"2", "5", "1", "3", new Boolean(false)},
            {"4", "1", "5", "2", new Boolean(false)}, {"5", "3", "4", "1", new Boolean(false)},
            {"1", "3", "2", "4", new Boolean(false)}, {"2", "5", "1", "3", new Boolean(false)},
            {"4", "1", "5", "2", new Boolean(false)}, {"5", "3", "4", "1", new Boolean(false)},
            {"1", "3", "2", "4", new Boolean(false)}, {"2", "5", "1", "3", new Boolean(false)},
            {"4", "1", "5", "2", new Boolean(false)}, {"5", "3", "4", "1", new Boolean(false)},
            {"1", "3", "2", "4", new Boolean(false)}, {"2", "5", "1", "3", new Boolean(false)},
            {"4", "1", "5", "2", new Boolean(false)}, {"5", "3", "4", "1", new Boolean(false)},
            {"1", "3", "2", "4", new Boolean(false)}, {"2", "5", "1", "3", new Boolean(false)},
            {"4", "1", "5", "2", new Boolean(false)}, {"5", "3", "4", "1", new Boolean(false)}};
        JTable table = new JTable();
        MyModel model = new MyModel(Color.RED, table.getBackground());
        model.setDataVector(data, columnNames);
        table.setModel(model);
        //table.setColumnSelectionAllowed(true);
        //table.setDefaultRenderer(Object.class, new TestCellRenderer());
        SelectionListener listener = new SelectionListener(table);
        table.getSelectionModel().addListSelectionListener(listener);
        table.getColumnModel().getSelectionModel().addListSelectionListener(listener);
        //table.setBackground(Color.green);
        JScrollPane scrollPane = new JScrollPane(table);
        contentPanel.add(scrollPane);
        contentPanel.setOpaque(true);
        frame.add(contentPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    static class TestCellRenderer extends DefaultTableCellRenderer {

        private static final long serialVersionUID = 1L;

        @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();
            c.setBackground(model.getCellColor(row, column));
            return c;
        }
    }

    static class MyModel extends DefaultTableModel {

        private static final long serialVersionUID = 1L;
        private Object selectedObject;
        private Color selectedColor;
        private Color normalColor;

        public MyModel(Color selectedColor, Color normalColor) {
            this.selectedColor = selectedColor;
            this.normalColor = normalColor;
        }

        public Color getCellColor(int row, int column) {
            if (getValueAt(row, column).equals(selectedObject)) {
                return selectedColor;
            }
            return normalColor;
        }

        public void setSelectedObject(Object selectedObject) {
            this.selectedObject = selectedObject;
            fireTableRowsUpdated(0, getRowCount());
        }

        @Override
        public Class getColumnClass(int c) {
            /* Need this so that Boolean columns render as checkboxes */
            return getValueAt(0, c).getClass();
        }
    }

    static class SelectionListener implements ListSelectionListener {

        private JTable table;

        SelectionListener(JTable table) {
            this.table = table;
        }

        @Override
        public void valueChanged(ListSelectionEvent e) {
            int rowIndex = table.getSelectedRow();
            int colIndex = table.getSelectedColumn();
            if (!e.getValueIsAdjusting() && colIndex != -1 && rowIndex != -1) {
                ((MyModel) table.getModel()).setSelectedObject(table.getValueAt(rowIndex, colIndex));
            }
        }
    }

    public static void main(String[] args) {
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    UIManager.getLookAndFeelDefaults().put("Table:\"Table.cellRenderer\".background",
                            new ColorUIResource(Color.WHITE));
                    UIManager.getLookAndFeelDefaults().put("Table.alternateRowColor", Color.WHITE);
                    break;
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • Hmm, I added my green coloring into this but instead of alternating, the boolean column does not get colored green at all (I'd like to color the entire row green). – Brent Oct 09 '15 at 20:43