Swing JTables of Java by default does not handle frequent updates and a huge number of columns and rows. I created a lighted version of JTable called FastJTable based on the code of the Java Christmas Tree.
This implementation is pretty faster when handling huge amounts of data. Consider taking a look at how the memory works if this is your use case.
/**
* Based on Sun's CTTable (Christmas Tree):
* https://java.sun.com/products/jfc/tsc/articles/ChristmasTree/
*
* @author marias
*/
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.CellRendererPane;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.TableModel;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Based on CTTable from Christmas Tree:
* https://java.sun.com/products/jfc/tsc/articles/ChristmasTree/
*
* @author marias marias@emergya.es
*/
public class FastJTable extends JTable {
private static final Log log = LogFactory.getLog(FastJTable.class);
private static final long serialVersionUID = -3218140266706898440L;
private JScrollPane scrollPane;
public FastJTable(TableModel model) {
super(model);
}
public void updateUI() {
super.updateUI();
setUI(new FastTableUI(this));
}
private static class FastTableUI extends BasicTableUI {
public FastTableUI(FastJTable table) {
super();
installUI(table);
}
@Override
public void installUI(JComponent c) {
// Overriden to install our own CellRendererPane
super.installUI(c);
c.remove(rendererPane);
rendererPane = new FastCellRendererPane();
c.add(rendererPane);
}
}
/**
* FastCellRendererPane overrides paintComponent to NOT clone the Graphics
* passed in and NOT validate the Component passed in. This will NOT work if
* the painting code of the Component clobbers the graphics (scales it,
* installs a Paint on it...) and will NOT work if the Component needs to be
* validated before being painted.
*/
private static class FastCellRendererPane extends CellRendererPane {
private static final long serialVersionUID = 4811773663334451913L;
private JViewport viewport;
public FastCellRendererPane() {
super();
}
// Can be ignored, we don't exist in the containment hierarchy.
public void repaint() {
}
@Override
public void paintComponent(Graphics g, Component c, Container p, int x,
int y, int w, int h, boolean shouldValidate) {
try {
if (c == null || !isVisible(new Rectangle(x, y, w, h))) {
log.trace("No lo pintamos (" + c + ")");
return;
}
// if (p != null) {
// Color oldColor = g.getColor();
// g.setColor(p.getBackground());
// g.fillRect(x, y, w, h);
// g.setColor(oldColor);
// }
if (c.getParent() != this) {
this.add(c);
}
c.setBounds(x, y, w, h);
// As we are only interested in using a JLabel as the renderer,
// which does nothing in validate we can override this to do
// nothing, if you need to support components that can do
// layout,
// this will need to be commented out, or conditionally
// validate.
if (!(c instanceof JLabel))
c.validate();
// JComponent jc = (c instanceof JComponent) ? (JComponent) c
// : null;
// jc.setDoubleBuffered(true);
// Don't create a new Graphics, reset the clip and translate
// the origin.
Rectangle clip = g.getClipBounds(c.getBounds());
g.clipRect(x, y, w, h);
g.translate(x, y);
c.paint(g);
g.translate(-x, -y);
g.setClip(clip.x, clip.y, clip.width, clip.height);
c.setBounds(-w, -h, 0, 0);
} catch (Throwable t) {
log.error("Error al pintar el componente de la tabla ", t);
}
}
/**
* We only paint the visible parts of the JTable.
* @param rectangle visible
* @return if it has to be painted on screen
*/
public boolean isVisible(Rectangle rectangle) {
if (viewport == null)
return true;
Rectangle visRect = viewport.getViewRect();
int xmin = ((Double) rectangle.getMinX()).intValue();
int ymin = ((Double) rectangle.getMinY()).intValue();
int xmax = ((Double) rectangle.getMaxX()).intValue();
int ymax = ((Double) rectangle.getMaxY()).intValue();
return (visRect.contains(new Point(xmin, ymin))
|| visRect.contains(new Point(xmax, ymin))
|| visRect.contains(new Point(xmin, ymax)) || visRect
.contains(new Point(xmax, ymax)));
}
}
}
One thought on “FastJTable”