在JTable中更改行的背景颜色

24

我有一个包含3列的JTable。我已经像这样为所有3列设置了TableCellRenderer(可能不是非常有效?)。

 for (int i = 0; i < 3; i++) {
     myJTable.getColumnModel().getColumn(i).setCellRenderer(renderer);
 }

getTableCellRendererComponent()方法为每一行返回一个带有随机背景颜色的组件。
我该如何在程序运行时将背景改为另一种随机颜色呢?

5个回答

31

Richard Fearn的答案概括如下,使每隔一行变为灰色:

jTable.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()
{
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        final Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        c.setBackground(row % 2 == 0 ? Color.LIGHT_GRAY : Color.WHITE);
        return c;
    }
});

你说得对,这个是有效的,但为什么只对前5列有效呢?有什么想法吗? - Disapamok
@Sahan 因为在第五列之外可能会有自定义的单元格渲染器。 - Enkuushka
我尝试了这个Olivier,但在使用上述代码后,效果是我不能再使用.setSelectionBackground(Color.yellow);了... :( - gumuruh
@gumuruh,你也可以通过使用提供的isSelected参数在渲染器中设置选择颜色。 - User892313
这样可以正常工作,但我还设置了JTable的整行选择功能。正在寻找一个与JTable.setRowSelectionAllowed(true)正确配合的解决方案。 - Pekmezli Dürüm

24

一种方法是在模型内为每一行存储当前颜色。这是一个简单的模型,它固定为3列和3行:

static class MyTableModel extends DefaultTableModel {

    List<Color> rowColours = Arrays.asList(
        Color.RED,
        Color.GREEN,
        Color.CYAN
    );

    public void setRowColour(int row, Color c) {
        rowColours.set(row, c);
        fireTableRowsUpdated(row, row);
    }

    public Color getRowColour(int row) {
        return rowColours.get(row);
    }

    @Override
    public int getRowCount() {
        return 3;
    }

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

    @Override
    public Object getValueAt(int row, int column) {
        return String.format("%d %d", row, column);
    }
}
请注意,setRowColour调用了fireTableRowsUpdated;这将导致表格中仅更新该行。
渲染器可以从表格中获取模型:
static class MyTableCellRenderer extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        MyTableModel model = (MyTableModel) table.getModel();
        Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        c.setBackground(model.getRowColour(row));
        return c;
    }
}

改变一行的颜色非常简单:

model.setRowColour(1, Color.YELLOW);

1
为什么模型需要了解颜色?这是否会破坏MVC模式? - undefined
为什么模型应该了解颜色?这是否会破坏MVC模式? - Zerumi

16
其他给出的答案在每一列中使用相同的渲染器,效果很好。
然而,我倾向于认为通常情况下,在使用JTable时,每一列都会有不同类型的数据,因此您不会为每一列使用相同的渲染器。在这些情况下,您可能会发现表格行渲染方法很有帮助。
本质上,它建议重写JTable的prepareRenderer方法。
JTable table = new JTable(...)
{
    public Component prepareRenderer(
        TableCellRenderer renderer, int row, int column)
    {
        Component c = super.prepareRenderer(renderer, row, column);

        //  add custom rendering here

        return c;
    }
};

1
我同意。在我看来,TableModel 应该保存表格数据。渲染应该在其他地方进行。链接的文章很有启发性,谢谢! :) - Matthieu
我喜欢这个想法,你可以替换单元格渲染器,但仍然保持一致的行颜色。 - Queeg

1

这基本上就像重新绘制表格一样简单。然而,我还没有找到只选择性地重绘制一行/一列/一个单元格的方法。

在这个例子中,点击按钮会更改一行的背景颜色,然后调用repaint方法。

public class TableTest {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final Color[] rowColors = new Color[] {
                randomColor(), randomColor(), randomColor()
        };
        final JTable table = new JTable(3, 3);
        table.setDefaultRenderer(Object.class, new TableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table,
                    Object value, boolean isSelected, boolean hasFocus,
                    int row, int column) {
                JPanel pane = new JPanel();
                pane.setBackground(rowColors[row]);
                return pane;
            }
        });
        frame.setLayout(new BorderLayout());

        JButton btn = new JButton("Change row2's color");
        btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                rowColors[1] = randomColor();
                table.repaint();
            }
        });

        frame.add(table, BorderLayout.NORTH);
        frame.add(btn, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

    private static Color randomColor() {
        Random rnd = new Random();
        return new Color(rnd.nextInt(256),
                rnd.nextInt(256), rnd.nextInt(256));
    }
}

1
调用getTableCellRendererComponent(...) 的时候包括所寻找的单元格的值。
您可以使用该值计算颜色。 如果还使用AbstractTableModel,则可以向渲染器提供任意类型的值。
有了颜色,您可以在返回的组件上使用setBackground()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接