1

I think I have a weird problem here. Here is my code:

private class BorderCellRenderer extends DefaultTableCellRenderer {
    private Border extraBorder;
    /**
     * A cell render is based on labels which are changed to display the correct appearance
     * This cell renderer adds extra border to every render action
     */
    BorderCellRenderer(Border extraBorder) {
        this.extraBorder = extraBorder;
    }


    /**
     * The setBorder() is used to change the cell appearance.
     * The trick is to override the call (of JComponent) and to add extra space
     * to it by making it an compound border with.
     *
     * Remember that getBorder() now returns our compound border
     */
    public void setBorder(Border border) {
        super.setBorder(new CompoundBorder(border, extraBorder));
    }

    public Component getTableCellRendererComponent(JTable table, Object value,
                                                    boolean isSelected, boolean hasFocus,
                                                    int row, int column) {
        setFont(table.getFont());
        setText(value.toString());

        /* set color depending on the state of the row */
        TableRowItem rowItem = ((FooModel) table.getModel()).getRow(row);

        String state = rowItem.getState();

        /* set tool tip on EMPLOYEE column */
        if(column == FooModel.COL_EMPLOYEE) {
            setToolTipText("blalba");
        }

        /* Paint text according to state*/
        if(state.equals(RowItemState.ENTERED)) {
            setForeground(Color.black);
            //TODO setSelectionForeground(Color.black);
        }
        if(state.equals(RowItemState.SUBMITTED)) {
            setForeground(Color.blue);
            //TODO setSelectionForeground(Color.blue);
        }
        if(state.equals(RowItemState.APPROVED)) {
            Color green = new Color(0, 128, 0); // greenish
            setForeground(green);
            //TODO setSelectionForeground(green);
        }
        if(state.equals(RowItemState.BOOKED)) {
            setForeground(Color.red);
            //TODO setSelectionForeground(Color.red);
        }

            switch (column) {
            case FooModel.COL_EMPLOYEE:
            case FooModel.COL_SAT:
            case FooModel.COL_SUN:
                if(state.equals(RowItemState.CHECKED)) {
                    setBackground(new Color(183, 244,176)); //light green
                } else {
                    setBackground(java.awt.Color.lightGray);
                }
                break;
            default:
                if(state.equals(RowItemState.CHECKED)) {
                    setBackground(new Color(183, 244,176)); //light green
                } else {
                    setBackground(java.awt.Color.white);
                }
                break;
            }
       //}

        if (column == FooModel.COL_TOTAL){
            if (table.getSelectedRowCount() > 0){
                int rowsSelected[] = table.getSelectedRows();
                double total = 0;
                for (int j = 0; j < table.getSelectedRowCount(); j++){
                    Double dTemp = (Double) table.getValueAt(rowsSelected[j], FooModel.COL_TOTAL);
                    total += dTemp.doubleValue();
                }
                setToolTipText("Total Selected = " + String.valueOf(total));
            }
        }

        // return super method for selections
        return super.getTableCellRendererComponent(table, value,
                                                    isSelected, hasFocus,
                                                    row, column);
    }
}

Now we get to the fun part. This code example runs fine, however when I uncomment the TODO lines so that the setSelectionForeground() methods are called, my CPU gets to like 20% on a Quad-Core. This happens on all my colleagues PC's as well (also Quad-Cores). When the lines are commented, CPU is around 0-1%. I find this very strange and cannot figure out what is going wrong here. I hope you can help me.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
lugte098
  • 2,271
  • 5
  • 21
  • 30
  • 2
    Seeing as `DefaultTableCellRenderer` doesn't have `setSelectionForeground`, I would assume this is a inner class of something like, a `JTable` you've implemented, which would then suggest that each time you call `setSelectionForeground`, the table is trying to re-render any cells that might be selected, as well as fire property change events and generally getting itself caught in a nasty loop of updates... – MadProgrammer Jul 29 '13 at 08:06
  • This is indeed an inner class of a JTable. So do you mean that setSelectionForeground is a method of the JTable and not the renderer? – lugte098 Jul 29 '13 at 08:11
  • That's correct. Try typing `this.setSelectionForeground(Color.BLUE)` within the context of the cell renderer and see if it will compile. – MadProgrammer Jul 29 '13 at 08:15
  • you're right, ok so now i need to find out how to get it working using other methods – lugte098 Jul 29 '13 at 08:20
  • 4
    the job of the renderer is to ... render :-) **Nothing else**. F.i. calculation of the actual tooltip belongs elsewhere (f.i. into a selectionListener) And - as already noted, just for emphasis - **don't** change the state of the caller (here: the table), ever – kleopatra Jul 29 '13 at 08:22

2 Answers2

6

Invoking setSelectionForeground() schedules a call to repaint() each of the four times time it is called for every cell. Instead,

  • Do not call setSelectionForeground() in the renderer.

  • Condition the color once based on the value of isSelected.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
2

use

  1. and to test coordinates boolean isSelected, boolean hasFocus, int row, int column (isSelected/hasFocus)

  2. getValue from XxxTableModel by strictly convertViewToModel (e.g. JTables view can be sorted or filtered)

  3. job for prepareRenderer

mKorbel
  • 109,525
  • 20
  • 134
  • 319