jTable paint() leads to java.lang.OutOfMemoryError: Java heap space

I am trying to build jTable in which I have a heavy (not very heavy) task of painting each cell of jTable. But I'm not painting very frequently (painting/updating each cell very rarely). After implementing jTable I encountered java.lang.OutOfMemoryError: Java heap space. I figured out that it is due to the call to paint(Graphics g, JComponent c) each microsecond. I don't wish to call this method all the time only in the case when table gets updated/modified. Is there any way to solve this problem?

Edit:

I have not called paint manually. The table has a manually created UI which is set using the setUI method. I have used this UI to create cells that can span multiple rows or columns (i.e. to merge few cells together).

setUI(new MultiSpanCellTableUI());

The class MultiSpanCellTableUI implements a paint() method which is getting called every second.

public void paint(Graphics g, JComponent c) { Rectangle oldClipBounds = g.getClipBounds(); Rectangle clipBounds = new Rectangle(oldClipBounds); int tableWidth = table.getColumnModel().getTotalColumnWidth(); clipBounds.width = Math.min(clipBounds.width, tableWidth); g.setClip(clipBounds); int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y)); int lastIndex = table.getRowCount() - 1; Rectangle rowRect = new Rectangle(0, 0, tableWidth, table.getRowHeight() + table.getRowMargin()); rowRect.y = firstIndex * rowRect.height; for (int index = firstIndex; index <= lastIndex; index++) { if (rowRect.intersects(clipBounds)) { paintRow(g, index); } rowRect.y += rowRect.height; } g.setClip(oldClipBounds); } private void paintRow(Graphics g, int row) { System.out.println("paintRow called"); Rectangle rect = g.getClipBounds(); boolean drawn = false; AttributiveCellTableModel tableModel = (AttributiveCellTableModel) table .getModel(); CellSpan cellAtt = (CellSpan) tableModel.getCellAttribute(); int numColumns = table.getColumnCount(); for (int column = 0; column < numColumns; column++) { Rectangle cellRect = table.getCellRect(row, column, true); int cellRow, cellColumn; if (cellAtt.isVisible(row, column)) { cellRow = row; cellColumn = column; } else { cellRow = row + cellAtt.getSpan(row, column)[CellSpan.ROW]; cellColumn = column + cellAtt.getSpan(row, column)[CellSpan.COLUMN]; } if (cellRect.intersects(rect)) { drawn = true; System.out.println("paintCell called!"); paintCell(g, cellRect, cellRow, cellColumn); } else { if (drawn) break; } } } private void paintCell(Graphics g, Rectangle cellRect, int row, int column) { int spacingHeight = table.getRowMargin(); int spacingWidth = table.getColumnModel().getColumnMargin(); Color c = g.getColor(); g.setColor(table.getGridColor()); g.drawRect(cellRect.x, cellRect.y, cellRect.width - 1, cellRect.height - 1); g.setColor(c); cellRect.setBounds(cellRect.x + spacingWidth / 2, cellRect.y + spacingHeight / 2, cellRect.width - spacingWidth, cellRect.height - spacingHeight); if (table.isEditing() && table.getEditingRow() == row && table.getEditingColumn() == column) { Component component = table.getEditorComponent(); component.setBounds(cellRect); component.validate(); } else { TableCellRenderer renderer = table.getCellRenderer(row, column); Component component = table.prepareRenderer(renderer, row, column); if (component.getParent() == null) { rendererPane.add(component); } rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y, cellRect.width, cellRect.height, true); } }

Since it is called every second, after a while the OutOfMemoryError occurs. I only need to repaint the cells when I update something in the cell and that information I can obtain easily. But how can I limit the calls to paint() based on that information?

-------------Problems Reply------------

not sure why do you needed

1) painting by paint(), please for which type of Components in the JTable's Cell, if is there some JComponent the you have to override paintComponent() instead of paint()

2) not good design to perform custom painting in the larger JTable

3) you have to look at Renderer, better would be prepareRenderer if you painting by using some Color

4) JTable by default returns JLabel, there you can set Icon instaead of prerform some custom painting

5) maybe help you with JTable's performance Christmas Tree Applications

With no code posted above, I assume you are forcing a paint() on the JTable component. There should not be a need to call paint() on the JTable object. To customize cell painting, use a TableCellRenderer instead.

public class MyCellRenderer extends JLabel implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) {
if (isSelected) {
// Is cell selected?
}
if (hasFocus) {
// Does this cell have the focus
}
// Configure the component with the specified value, here we are using JLabel
setText(value.toString());
// Set tool tip if desired
setToolTipText((String)value);
// Since the renderer is a component, return itself
return this;
}
}

Category:java Views:0 Time:2011-12-21

Related post

Copyright (C) dskims.com, All Rights Reserved.

processed in 0.182 (s). 11 q(s)