简体   繁体   中英

Set color of each row in JTable - Java Swing

I want to set the color for each row of my JTable to a different one depending on a calculation made before. However, the calculation is correct and it fires the setRowColor() method written by myself with the correct color but the color of the whole table gets set.

So, if the last element is orange the whole table gets set to orange although the setRowColor() method gets called with another color. Same goes for any other color. You can see this on the console output here:

Row 0: White
Row (0) & Cell (0) to java.awt.Color[r=255,g=255,b=255]
Row (0) & Cell (1) to java.awt.Color[r=255,g=255,b=255]
Row (0) & Cell (2) to java.awt.Color[r=255,g=255,b=255]


Row 1: Orange
Row (1) & Cell (0) to java.awt.Color[r=255,g=200,b=0]
Row (1) & Cell (1) to java.awt.Color[r=255,g=200,b=0]
Row (1) & Cell (2) to java.awt.Color[r=255,g=200,b=0]

It always sets the entire table to the last color called! Why is that and how can I fix this? Here is my code:

private void setRowColor(int row, Color color){

        for (int i = 0; i < 3; i++) {
            TableCellRenderer tableCellRenderer = sellTable.getCellRenderer(row, i);
            Component c = sellTable.prepareRenderer(tableCellRenderer, row, i);
            c.setBackground(color);

            System.out.println("Row (" + row + ") & Cell (" + i + ") to " + color.toString());
        }

        System.out.println();
        System.out.println();

    }

but the color of the whole table gets set.

The same renderer is used for all cells of the same data type in the table. So you can't set the Color of the renderer in advance. You need to set the color as each cell is rendered.

I want to set the color for each row of my JTable to a different one depending on a calculation

That calculation should be added to the rendering process. This will allow for dynamic coloring of the row if the data in the row changes.

An easy way to do this is to override the prepareRenderer(...) method of the table. A simple example of this approach is:

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

        //  Alternate row color

        if (!isRowSelected(row))
            c.setBackground(row % 2 == 0 ? getBackground() : Color.LIGHT_GRAY);

        return c;
    }
};

Check out Table Row Rendering for more information and an example on row highlighting based on the data found in each row.

It would only be possible if you make the background color part of the data model, that is to say, each value in each cell should contain both the display value and it's background color. Then you need to create and add a TableCellRenderer (and TableCellEditor if the table is editable) that renders your data.

For example, if you specify each data element as simple as Object[]{color, string} (not recommended; better create an immutable container class), you can get away with this:

(modified from https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#renderer )

public class ColorTextRenderer extends JLabel implements TableCellRenderer {
    public ColorTextRenderer() {
        setOpaque(true); //MUST do this for background to show up.
    }

    public Component getTableCellRendererComponent(
                            JTable table, Object value,
                            boolean isSelected, boolean hasFocus,
                            int row, int column) {
        setBackground((Color)((Object[])value)[0]);
        setText     ((String)((Object[])value)[1]);
        return this;
    }
}

Here is a small example for you, how to provide separate colors for each cell. What you need is to create a renderer, that can define colors for each cell and set it for all cells.

import java.awt.Color;
import java.awt.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableCellRenderer;

/**
 * <code>ColoredRenderer</code>.
 */
public class ColoredRenderer {

    public static void main(String[] args) {
        ColorRenderer renderer = new ColorRenderer();
        renderer.setColorForCell(0, 0, Color.YELLOW);
        renderer.setColorForCell(1, 0, Color.CYAN);
        renderer.setColorForCell(2, 0, Color.GRAY);
        renderer.setColorForCell(3, 0, Color.BLUE);
        renderer.setColorForCell(4, 0, Color.GREEN);
        JTable table = new JTable(10, 5);
        // set my renderer for all cells. 
        table.setDefaultRenderer(Object.class, renderer); 
        // Probably in your code you need to set it for each column by using
        // table.getColumnModel().getColumn(columnIndex).setCellRenderer(renderer);
        JFrame frm = new JFrame("Color test");
        frm.add(new JScrollPane(table));
        frm.pack();
        frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frm.setLocationRelativeTo(null);
        frm.setVisible(true);
    }

    private static class ColorRenderer extends DefaultTableCellRenderer {
        private final Map<String, Color> colorMap = new HashMap<>();

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            setBackground(null);
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            getColorForCell(row, column).ifPresent(this::setBackground);
            return this;
        }

        public void setColorForCell(int row, int col, Color color) {
            colorMap.put(row + ":" + col, color);
        }

        public Optional<Color> getColorForCell(int row, int col) {
            return Optional.ofNullable(colorMap.get(row + ":" + col));
        }
    }
}

PS I use here some Java8 features (Optional + Method-reference). If it's required I can rewrite this code without these features.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM