TableCellRenderer将颜色设置为多个单元格,而不仅仅是一个单元格

时间:2015-03-01 23:08:24

标签: java swing jtable jlabel tablecellrenderer

我有一个JTable,我希望我能够更改单击的单个单元格的颜色。

以下是我的代码的简化版本:

public class TableFrame extends JFrame {

    public TableFrame() {
        JTable table = new JTable(8, 8);
        table.setGridColor(Color.BLACK);
        table.setDefaultRenderer(CustomCellRenderer.class, new CustomCellRenderer());
        getContentPane().add(table);
    }

    public class CustomCellRenderer extends DefaultTableCellRenderer {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if (hasFocus) {
                l.setBackground(Color.red);
                l.setText("Hello");
            }
            return l;
        }
    }
}

当我点击某个单元格时,我希望它将颜色更改为红色并添加“Hello”。它改变了文本,但出于某些奇怪的原因,它会改变所有单元格的颜色吗?当我点击一个未着色的单元格时,它会做同样的事情,但如果有意义的话,并不总是以有条理的方式进行?比如,它不会为它之后的所有细胞着色,但也许有些只是在上面并且让其他人留空......

这真的很奇怪,没有任何意义。发生了什么事?

2 个答案:

答案 0 :(得分:3)

稍微挖了DefaultTableCellRenderer类,当你在支持setBackground的{​​{1}}组件上调用JLabel时,它会存储你使用的值...

DefaultTableCellRenderer

当再次绘制单元格时,它是用于重新绘制单元格的值(public void setBackground(Color c) { super.setBackground(c); unselectedBackground = c; } ),默认为"模式...

unselectedBackground

这意味着,当您使用 if (isSelected) { //... } else { Color background = unselectedBackground != null ? unselectedBackground : table.getBackground(); if (background == null || background instanceof javax.swing.plaf.UIResource) { Color alternateColor = DefaultLookup.getColor(this, ui, "Table.alternateRowColor"); if (alternateColor != null && row % 2 != 0) { background = alternateColor; } } super.setForeground(unselectedForeground != null ? unselectedForeground : table.getForeground()); super.setBackground(background); } 并将其传递给setBackground时,Color.RED会假定这成为所有未选定单元格的默认颜色。

您唯一的选择是手动重置背景颜色,例如......

DefaultTableCellRenderer

另外,你应该使用更像......的东西。

public class CustomCellRenderer extends DefaultTableCellRenderer {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        if (hasFocus) {
            l.setBackground(Color.red);
            l.setText("Hello");
        } else if (!isSelected) {
            l.setBackground(table.getBackground());
        }
        return l;
    }
}

注册单元格渲染器,因为它是由table.setDefaultRenderer(Object.class, new CustomCellRenderer()); 返回的Class类型,用于确定使用哪个单元格渲染器;)

答案 1 :(得分:1)

由于OP只需要渲染的帮助而不需要数据...这里有(假设有一个名为hasBeenClicked(row,column)的函数可用于确定单元格是否已被访问尚未。

public class CustomCellRenderer extends DefaultTableCellRenderer {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        if (hasBeenClicked(row,column)) {
            l.setBackground(Color.red);
            l.setText("Hello");
        } else {
            // reset the label to white background
            l.setBackground(Color.white);
            l.setText("Hello");
        }
        return l;
    }
}

}

另请注意,渲染器的注册应为

  table.setDefaultRenderer(Object.class, new CustomCellRenderer());

由于我们希望所有列都具有此渲染器(渲染器是针对模型中列的类注册的)。

我使用以下hasBeenClicked方法进行了测试。

public boolean hasBeenClicked(int row, int column){
    return (row%2==0 && column%2==0);
}

只需实现自己跟踪是否已点击某个单元格,您应该好好去。请记住,您不应该使用渲染器来跟踪点击次数,而是使用某种类型的侦听器。