Search code examples
javaswingcolorsjtabletablecellrenderer

How to make a JTable with multiple Components?


I have a JTable that I want to apply two prepareRenderer methods to, but I'm not sure how I can apply both.

JTable table = new JTable(model){

        public Component prepareRenderer(TableCellRenderer renderer, int row, int column){
            Component returnComp = super.prepareRenderer(renderer, row, column);
            Color alternateColor = new Color(241, 243, 247);
            Color whiteColor = Color.WHITE;
            if (!returnComp.getBackground().equals(getSelectionBackground())){
                Color bg = (row % 2 == 0 ? alternateColor : whiteColor);
                returnComp .setBackground(bg);
                bg = null;
            }
            return returnComp;
        }


        public Component prepareRenderer2(TableCellRenderer renderer, int rowIndex,
                int columnIndex) {
            JComponent component = (JComponent) super.prepareRenderer(renderer, rowIndex, columnIndex);  

            if(Double.parseDouble(getValueAt(rowIndex, 0).toString()) > (Double.parseDouble(rollReq.getText())) && columnIndex == 6) {
                component.setBackground(Color.RED);
            } else if(Double.parseDouble(getValueAt(rowIndex, 0).toString()) > (Double.parseDouble(rollReq.getText())) && columnIndex == 6){
                component.setBackground(Color.GREEN);
            }
            return component;
        }

    };`

The first one is to make one row white, and the next row grey, for easier readability. And the second one is to change the cell color of a column based on it's value.

Any help would be appreciated.

Thank you!


Solution

  • The first one is to make one row white, and the next row grey, for easier readability. And the second one is to change the cell color of a column based on it's value.

    Not sure why you think you need two prepareRenderers. Just merge the logic into one:

    public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
    {
        Component c = super.prepareRenderer(renderer, row, column);
    
        //  Color row based on a cell value
    
        if (!isRowSelected(row))
        {
            //c.setBackground(getBackground()); //removed
            c.setBackground(row % 2 == 0 ? getBackground() : Color.LIGHT_GRAY); // added
            int modelRow = convertRowIndexToModel(row);
            String type = (String)getModel().getValueAt(modelRow, 0);
    
            if ("Buy".equals(type)) c.setBackground(Color.GREEN);
            if ("Sell".equals(type)) c.setBackground(Color.YELLOW);
        }
    
        return c;
    }
    

    The above code was "combined" from the "Data Example" found in Table Row Renderring.

    So all you need to do is slightly restructure your code using the above structure:

    1. check if row is selected
    2. set the alternating color background
    3. override alternating color with data based check for background color

    Also, you should not use columnIndex. The user may have reordered the columns.

    (Double.parseDouble(getValueAt(rowIndex, 0).toString()) >
        (Double.parseDouble(rollReq.getText())) && columnIndex == 6) 
    

    Instead you should use:

    int modelColumn convertColumnIndexToModel(columnIndex));
    (Double.parseDouble(getValueAt(rowIndex, 0).toString()) >
        (Double.parseDouble(rollReq.getText())) && modelColumn == 6) 
    

    For the same reason you should not use: getValueAt(rowIndex, 0). Again the column may be moved.