2011-12-21 10 views
1

jTableの各セルをペイントする重い(あまり重くない)タスクを持つjTableを構築しようとしています。しかし、私は非常に頻繁に絵を描いているわけではありません。 jTableを実装した後、私はjava.lang.OutOfMemoryError: Java heap spaceに遭遇しました。私はそれがpaint(Graphics g, JComponent c)に1マイクロ秒の呼び出しのためにあることを理解しました。テーブルが更新/変更された場合にのみ、常にこのメソッドを呼びたくはありません。この問題を解決する方法はありますか?jTable paint()はjava.lang.OutOfMemoryErrorにつながります。Javaヒープスペース

編集:私は手動で塗料を呼び出していない

。このテーブルには、setUIメソッドを使用して手動で作成されたUIが設定されています。このUIを使用して、複数の行または列にまたがる(つまり、少数のセルを結合する)セルを作成しました。

setUI(new MultiSpanCellTableUI());

クラスMultiSpanCellTableUIは毎秒呼ばなっているpaint()メソッドを実装します。 OutOfMemoryErrorが行われている間、それが後に、毎秒呼び出されるので

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); 
    } 
} 

。私は、細胞内の何かを更新するときに細胞を再描画する必要があり、簡単に得ることができる情報です。しかし、その情報に基づいてどのようにしてpaint()に電話を制限できますか?あなたが持っているpaintComponent()を上書きする代わりにpaint()

2してくださいいくつかのJComponentがあれば、JTable's Celリットル内のコンポーネントのタイプのためにあなたは、paint()によって

1)塗装を必要としない理由

+3

[sscce](http://www.sscce.org)を含めてください。また、 'paint'を明示的に呼び出すべきではありません。 – mre

+0

@Крысaそれに応じて質問を更新しました。 –

+0

例:http://www.java2s.com/Code/Java/Swing-Components/MultiSpanCellTableExample.htmを試してみましたが、大したことはもうありません。 – mKorbel

答えて

2

わかりません)ではない良いデザインはカスタムペイントを実行するために、より大きなJTable

3)あなたは、いくつかの色

012を使用してペイントした場合、より良い prepareRendererになり、 Rendererを見ていますデフォルトのリターンによって

4)JTableJLabel、そこにあなたが多分上記の掲示がないコードでJTable'sパフォーマンスChristmas Tree Applications

+0

+1クリスマスツリーアプリ+1 – GETah

1

のお手伝いをする)prerformいくつかのカスタムペイント

5のIcon instaeadを設定することができ、私はあなたが強制されていると仮定JTableコンポーネントのpaint()JTableオブジェクトでpaint()に電話する必要はありません。セルペイントをカスタマイズするには、代わりにTableCellRendererを使用します。

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; 
    } 
} 
+0

hmmm基本的なもの – mKorbel

関連する問題