Difficulties understanding the renderers mechanism of swing's JTable and JTree

It's an implementation of the flyweight pattern.

When the JTable repaints itself, it starts a loop and iterates over every cell that must be painted.

For each cell, it invokes the renderer with the arguments corresponding to the cell. The renderer returns a component. This component is painted in the rectangle corresponding to the current table cell.

Then the renderer is called for the next cell, and the returned component (which has a different text and color, for example), is painted in the rectangle corresponding to the cell, etc.

Imagine that each time the renderer is called, a screenshot of the returned component is taken and pasted into the table cell.


In adition to @JB's clear explication of how JTable and JTree use the flyweight pattern, note how both classes provide public methods getCellRenderer() and getCellEditor(). Examine these methods to see how JTable uses Class Literals as Runtime-Type Tokens to select a renderer or editor by class, if none is specified by column. Internally, JTable uses a Hashtable defaultRenderersByColumnClass for instance storage.


After some digging, found the next implementation note from DefaultTableCellRenderer documentation:

Implementation Note: This class inherits from JLabel, a standard component class. However JTable employs a unique mechanism for rendering its cells and therefore requires some slightly modified behavior from its cell renderer. The table class defines a single cell renderer and uses it as a as a rubber-stamp for rendering all cells in the table; it renders the first cell, changes the contents of that cell renderer, shifts the origin to the new location, re-draws it, and so on. The standard JLabel component was not designed to be used this way and we want to avoid triggering a revalidate each time the cell is drawn. This would greatly decrease performance because the revalidate message would be passed up the hierarchy of the container to determine whether any other components would be affected. As the renderer is only parented for the lifetime of a painting operation we similarly want to avoid the overhead associated with walking the hierarchy for painting operations. So this class overrides the validate, invalidate, revalidate, repaint, and firePropertyChange methods to be no-ops and override the isOpaque method solely to improve performance. If you write your own renderer, please keep this performance consideration in mind.

This is essentially what JB explained above.

Thanks for the (quick) answers