Question

//newbie question

I have a JTable with an almost basic cell renderer (it colors the line differently). I've noticed my cell renderer is constantly running for the lines that are displayed on the screen, even when I don't do anything with the table.

Is that how it's supposed to be? Shouldn't it have rendered each cell once , and that's it? How can I make it stop , and only recalculate on change?

public Component getTableCellRendererComponent(JTable table, Object value,
    boolean isSelected, boolean hasFocus, int row, int column) {

   log.debug("Building cell : " + row + "," + column);

   Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

   Filter filter = (Filter)table.getModel().getValueAt(row, Column.CLASSIFICATION.getIndex());
   comp.setBackground(filter.getColor());
   return comp;

  }
Was it helpful?

Solution

I've worked a lot with JTables containing a lot of data. More than what 99.9% of Java programmers typically manipulate. There's one thing you need to know: by default there's an insane amount of waste generated and an insane amount of typically needless operation done.

If you're after fast and efficient JTables, then there's the authoritative Sun article on the subject:

"Christmas Tree Applications, How to Create Frequently-Updated JTables that Perform Well"

Notice the "that Perform Well" in the title, because by default JTable perfs are really, really pathetically bad:

Original Link (Sun)

Current link (Oracle)

Archived Version:

After implementing two or three of the techniques adviced in that article, you'll notice amazing speedup in your JTable rendering and you'll notice that much less garbage is generated (and hence the GC needs to kick in way less often).

OTHER TIPS

Following @Steve McLeod's offer , I started building an example code with the same bug , and only then I realized that inside one of my CellRenderers

@Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {

        log.debug("Building a list for " + row + "," + column);
        setListData(((Vector<String>)value).toArray());     
        setToolTipText("This is a tool tip for " + row + "," + column);

        table.setRowHeight(row, Math.max(1, getPreferredSize().height));
        Filter filter = (Filter)table.getModel().getValueAt(row, Column.CLASSIFICATION_RESULT.getIndex());
        setBackground(filter.getColor());       
        return this;
    }

I had the line :

table.setRowHeight(row, Math.max(1, getPreferredSize().height));

and it constantly changed the row line , while the other renderers in the same line did the same... so they were constantly firing each other.

I notice you change the appearance of a cell based on the value of another cell. If this relationship goes both ways - cell 1 appearance is based on cell 2 and vice versa you could get such a problem. But really, we need a self-contained code example that reproduces the problem - otherwise we can only shoot in the dark.

the renderer already caches your rendered component, when nothing changes nothing gets rerendered

However when the table detects something MIGHT have changed it will request a re-rendering. The event that triggers it the most is a mouse move.

So yes its normal behaviour for a JTable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top