Цветные ячейки таблицы

я хочу раскрасить ячейки таблицы в соответствии со значением в столбце 1, если значения не равны значению в столбце 1, цвет должен быть голубым, но мой код не работает:

table = new JTable(){
           public TableCellRenderer getCellRenderer(int row, int column) {
              TableCellRenderer tcr=null;
               Color c;
               if(column>=1&&getValueAt(row, column)!=null &&getValueAt(row, 1)!=null &&!getValueAt(row, column).equals(getValueAt(row, 1)))
                   c=Color.CYAN;
               else
                   c=Color.white;
                if(getValueAt(row, column) instanceof Boolean) {
                  tcr= super.getDefaultRenderer(Boolean.class);
                } else {
                  tcr=  super.getCellRenderer(row, column);
                }

               tcr.getTableCellRendererComponent(this, getValueAt(row, column), isCellSelected(row, column) , hasFocus(), row, column).setBackground(c);
               return tcr;

            }
            public TableCellEditor getCellEditor(int row, int column) {
                if(getValueAt(row, column) instanceof Boolean) {
                    return super.getDefaultEditor(Boolean.class);
                } else {
                    return super.getCellEditor(row, column);
                }
            }
    };
          table.setModel(new DefaultTableModel(
            new Object[][] {
             {"Row1", "1","2","3"},
             {"Row2", "2","2","3"},
             {"Row3", "2","2","2"},
             {"Row3", "2","1","2"}
                           },
            new String[] {"Header1", "Header2","Header3","Header4"}
    ));

person Jaran    schedule 24.03.2014    source источник
comment
Похоже, вы устанавливаете цвет фона вашего JTable вместо вашего Renderer?   -  person Peter Lang    schedule 24.03.2014
comment
я обновил его думаю теперь он работает   -  person Jaran    schedule 24.03.2014
comment
-1 за то, что снова задали один из самых часто задаваемых вопросов.... (лень искать дубликат)   -  person kleopatra    schedule 24.03.2014


Ответы (1)


Решение о том, должна ли ячейка быть выделена, должно быть принято в TableCellRenderer. Это нельзя сделать в JTable. Так что (вероятно) нет причин переопределять методы в JTable. Вместо этого вы можете установить CellRenderer для столбцов как собственную реализацию TableCellRenderer.

В этом примере столбцы 2 и 3 получают «ColoringCellRenderer». Этот ColoringCellRenderer выделит определенную ячейку, если значение в этой ячейке не равно нулю и совпадает со значением в столбце 1.

import java.awt.Color;
import java.awt.Component;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;


public class ColoredTableCells
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.getContentPane().add(new JScrollPane(createTable()));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    static JTable createTable()
    {
        class ColoringTableCellRenderer extends DefaultTableCellRenderer
        {
            ColoringTableCellRenderer()
            {
                setOpaque(true);
            }

            @Override
            public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column)
            {
                super.getTableCellRendererComponent(
                    table, value, isSelected, hasFocus, row, column);
                if (highlightCell(table, row, column))
                {
                    setBackground(Color.CYAN);
                }
                else
                {
                    setBackground(Color.WHITE);
                }
                return this;
            }

            private boolean highlightCell(JTable table, int row, int column)
            {
                Object thisValue = table.getValueAt(row, column);
                Object referenceValue = table.getValueAt(row, 1);
                if (thisValue != null && referenceValue != null)
                {
                    return thisValue.equals(referenceValue);
                }
                return false;
            }
        }

        JTable table = new JTable();
        table.setModel(new DefaultTableModel(new Object[][] {
            { "Row1", "1", "2", "3" },
            { "Row2", "2", "2", "3" },
            { "Row3", "2", "2", "2" }, 
            { "Row3", "2", "1", "2" } },
            new String[] { "Header1", "Header2", "Header3", "Header4" }));


        for (int i=2; i<table.getColumnCount(); i++)
        {
            TableColumn column = table.getColumnModel().getColumn(i);
            column.setCellRenderer(new ColoringTableCellRenderer());
        }
        return table;
    }
}

РЕДАКТИРОВАТЬ: ответ уже был принят, но в ответ на комментарии другая версия:

В нем используются два класса: «DelegatingTableCellRenderer» и «DelegatingTableCellEditor». Каждый из этих классов получает соответствующий делегат и устанавливает только цвет фона компонента ячейки, который доставляется делегатом.

Таким образом, функции раскрашивания ячеек таблицы (для средств визуализации или редакторов) отделены от фактического средства визуализации. Таким образом, можно раскрасить, например, фон CellRenderer по умолчанию для значений Boolean (который показывает JCheckBox).

import java.awt.Color;
import java.awt.Component;
import java.util.EventObject;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;


public class ColoredTableCells2
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.getContentPane().add(new JScrollPane(createTable()));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    static JTable createTable()
    {
        JTable table = new JTable()
        {
            @Override
            public Class<?> getColumnClass(int column) 
            {
                if (column == 0)
                {
                    return Object.class;
                }
                return Boolean.class;
            }
        };

        table.setDefaultEditor(Boolean.class, 
            new DelegatingTableCellEditor(table.getDefaultEditor(Boolean.class)));

        table.setDefaultRenderer(Boolean.class, 
            new DelegatingTableCellRenderer(table.getDefaultRenderer(Boolean.class)));

        table.setModel(new DefaultTableModel(new Object[][] {
            { "Row1", true,  false, true },
            { "Row2", true,  true,  false },
            { "Row3", false, false, true }, 
            { "Row3", false, true,  false } },
            new String[] { "Header1", "Header2", "Header3", "Header4" }));


        return table;
    }


    static class DelegatingTableCellEditor implements TableCellEditor
    {
        private final TableCellEditor delegate;

        DelegatingTableCellEditor(TableCellEditor delegate)
        {
            this.delegate = delegate;
        }

        @Override
        public Object getCellEditorValue()
        {
            return delegate.getCellEditorValue();
        }

        @Override
        public boolean isCellEditable(EventObject anEvent)
        {
            return delegate.isCellEditable(anEvent); 
        }

        @Override
        public boolean shouldSelectCell(EventObject anEvent)
        {
            return delegate.shouldSelectCell(anEvent);
        }

        @Override
        public boolean stopCellEditing()
        {
            return delegate.stopCellEditing();
        }

        @Override
        public void cancelCellEditing()
        {
            delegate.cancelCellEditing();
        }

        @Override
        public void addCellEditorListener(CellEditorListener l)
        {
            delegate.addCellEditorListener(l);
        }

        @Override
        public void removeCellEditorListener(CellEditorListener l)
        {
            delegate.removeCellEditorListener(l);
        }

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

            Component component = 
                delegate.getTableCellEditorComponent(
                    table, value, isSelected, row, column);
            if (component instanceof JComponent)
            {
                JComponent c = (JComponent)component;
                c.setOpaque(true);
            }
            if (highlightCell(table, row, column))
            {
                component.setBackground(Color.CYAN);
            }
            else
            {
                component.setBackground(Color.WHITE);
            }
            return component;
        }

    }


    static class DelegatingTableCellRenderer extends DefaultTableCellRenderer          
    {
        private final TableCellRenderer delegate;

        DelegatingTableCellRenderer(TableCellRenderer delegate)
        {
            this.delegate = delegate;
        }

        @Override
        public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column)
        {
            Component component = 
                delegate.getTableCellRendererComponent(
                    table, value, isSelected, hasFocus, row, column);
            if (component instanceof JComponent)
            {
                JComponent c = (JComponent)component;
                c.setOpaque(true);
            }
            if (highlightCell(table, row, column))
            {
                component.setBackground(Color.CYAN);
            }
            else
            {
                component.setBackground(Color.WHITE);
            }
            return component;
        } 
    }

    private static boolean highlightCell(JTable table, int row, int column)
    {
        if (column == 1)
        {
            return false;
        }
        Object thisValue = table.getModel().getValueAt(row, column);
        Object referenceValue = table.getModel().getValueAt(row, 1);
        if (thisValue != null && referenceValue != null)
        {
            return thisValue.equals(referenceValue);
        }
        return false;
    }

}
person Marco13    schedule 24.03.2014
comment
не понимаете и Q, и A, тогда +1 против голосующих - person mKorbel; 24.03.2014
comment
@mKorbel: И я не понимаю вашего комментария ;-) Вопрос был в том, я хочу раскрасить ячейки таблицы в соответствии со значением в столбце 1, если значения не равны значению в столбце 1, цвет должны быть голубыми - хорошо, мой код окрашивает их в голубой цвет, если они равны, но это можно исправить с помощью одного ! ... - person Marco13; 24.03.2014
comment
@ Marco13 Marco13, возможно ли совместить цветные ячейки и отображение флажка вместо true и false? я имею в виду, если модель похожа на новый объект[][] {{Row1, 1, 2, 3}, {Row2, 2, 2, 3}, {Row3, 2, 2, 2}, {Row4, true,false ,true } } потому что if(getValueAt(row, column) instanceof Boolean) { return super.getDefaultEditor(Boolean.class); ставит такой флажок - person Jaran; 24.03.2014
comment
в основном правильно (+1) просто немного придирки: а) нет необходимости снова брать текущее значение, оно передается как параметр б) рендерер должен быть автоматическим, то есть не полагаться на другой код, не устанавливающий себя в качестве рендерера для столбец сравнения c) сломается, если пользователь переупорядочит столбцы d) не имеет визуальной подсказки выбора (или другого украшения, такого как dnd) - но это действительно просто незначительное примечание, совершенно нормальное для пример кода :-) - person kleopatra; 24.03.2014
comment
@Jaran Я добавил РЕДАКТИРОВАТЬ с новой версией, я думаю, это то, о чем вы просили в комментарии. - person Marco13; 24.03.2014