当值改变时,JTable改变整列的颜色 - Swing

时间:2016-05-25 07:09:22

标签: java swing jtable tablecellrenderer

我试着在这里找了很长时间来回答我的问题,但没有我预期的确切结果。

我有JTable,每次我改变整列的值(每次只在一列中)。 我想听一个表格更改,当列中的数据发生变化时,列中的颜色也会改变,所有其他列都将采用默认颜色。

这是表监听器的代码:

Class CustomCellRenderer extends DefaultTableCellRenderer {

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

        Component rendererComp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

        table.getModel().addTableModelListener(new TableModelListener() {

            @Override
            public void tableChanged(TableModelEvent e) {
                if(***here i want to know which column changed or something like that***){
                    rendererComp.setBackground(Color.CYAN);
                }

            }
        });

        return rendererComp ;
    }

}

这是表创建的代码:

private void createTable() {

        tablePanel.setLayout(new FlowLayout(FlowLayout.LEFT));

        DefaultTableModel tableModel = new DefaultTableModel(){

            @Override
            public boolean isCellEditable(int row, int column) {
               //all cells false
               return false;
            }
        };
        contentTable = new JTable(tableModel);

        contentTable.setGridColor(Color.LIGHT_GRAY);

        for(int i=0; i<columnSize; i++) {
            tableModel.addColumn("0");
        }

        for(int i=0; i<rawSize; i++) {
            tableModel.addRow(new Object[] { "" });
        }

        for(int i=0; i<rawSize; i++) {
            for(int j=0; j<tableModel.getRowCount(); j++) {
                tableModel.setValueAt("0", j, i);
            }
        }

        for(int i=0; i<ramSize; i++) {
            contentTable.getColumnModel().getColumn(i).setCellRenderer(new CustomCellRenderer());
        }

        JScrollPane scrollPane = new JScrollPane(contentTable);
        scrollPane.setPreferredSize(new Dimension(400, 150));

        tablePanel.add(scrollPane);
}

1 个答案:

答案 0 :(得分:1)

将所需的状态存储在TableModel;让TableCellRenderer使用状态来相应地调整视图。在下面的示例中,只要setValueAt()更新任何单元格,edited就会标记为true。应用于列零的渲染会相应地更改显示。请注意clearEdited()如何调用fireTableDataChanged()强制表在 Clear 处理程序中调用时呈现所有单元格。

附录:下面的更新显示了一种独立处理多个列的方法。 CustomModel现在包含Map<Integer, Boolean>,用于存储应用CustomRenderer的每列的已编辑状态。另外,CustomRenderer现在调用convertColumnIndexToModel()并正确设置选择颜色。

image

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

/**
 * @see http://stackoverflow.com/a/37439731/230513
 */
public class Test {

    private void display() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        CustomModel model = new CustomModel();
        model.setColumnIdentifiers(new String[]{"A", "B"});
        for (int i = 0; i < 16; i++) {
            model.addRow(new String[]{"A:" + i, "B:" + i});
        }
        JTable table = new JTable(model) {
            @Override
            public Dimension getPreferredScrollableViewportSize() {
                return new Dimension(100, getRowHeight() * getRowCount() / 2);
            }
        };
        table.getColumnModel().getColumn(0).setCellRenderer(new CustomRenderer(model));
        table.getColumnModel().getColumn(1).setCellRenderer(new CustomRenderer(model));
        f.add(new JScrollPane(table));
        JPanel p = new JPanel();
        p.add(new JButton(new UpdateAction("Update A", model, 0)));
        p.add(new JButton(new UpdateAction("Update B", model, 1)));
        p.add(new JButton(new AbstractAction("Clear") {
            @Override
            public void actionPerformed(ActionEvent e) {
                model.clearEdited(0);
                model.clearEdited(1);
            }
        }));
        f.add(p, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static class CustomModel extends DefaultTableModel {

        private final Map<Integer, Boolean> edited = new HashMap<>();

        public boolean isEdited(int column) {
            return edited.get(column) != null && edited.get(column);
        }

        public void clearEdited(int column) {
            edited.put(column, false);
            fireTableDataChanged();
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }

        @Override
        public void setValueAt(Object aValue, int row, int column) {
            super.setValueAt(aValue, row, column);
            edited.put(column, true);
        }
    }

    private static class CustomRenderer extends DefaultTableCellRenderer {

        private final CustomModel model;

        public CustomRenderer(CustomModel model) {
            this.model = model;
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int col) {
            Component c = super.getTableCellRendererComponent(
                table, value, isSelected, hasFocus, row, col);
            if (model.isEdited(table.convertColumnIndexToModel(col))) {
                c.setBackground(Color.cyan);
            } else if (isSelected) {
                c.setBackground(table.getSelectionBackground());
            } else {
                c.setBackground(table.getBackground());
            }
            return c;
        }
    }

    private static class UpdateAction extends AbstractAction {

        private final CustomModel model;
        private final int column;

        public UpdateAction(String name, CustomModel model, int column) {
            super(name);
            this.model = model;
            this.column = column;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < model.getRowCount(); i++) {
                model.setValueAt(model.getValueAt(i, column), i, column);
            }
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Test()::display);
    }
}