jTable paint () приводит к java.lang.OutOfMemoryError: пространство кучи Java - PullRequest
1 голос
/ 21 декабря 2011

Я пытаюсь построить jTable, в котором у меня есть тяжелая (не очень тяжелая) задача покраски каждой ячейки jTable. Но я не очень часто рисую (очень редко рисую / обновляю каждую ячейку). После реализации jTable я столкнулся с java.lang.OutOfMemoryError: Java heap space. Я понял, что это связано с вызовом paint(Graphics g, JComponent c) каждую микросекунду. Я не хочу вызывать этот метод все время только в случае, когда таблица обновляется / модифицируется. Есть ли способ решить эту проблему?

Edit:

Я не вызывал краску вручную. Таблица имеет пользовательский интерфейс, созданный вручную с помощью метода setUI. Я использовал этот интерфейс для создания ячеек, которые могут занимать несколько строк или столбцов (то есть объединять несколько ячеек вместе).

setUI(new MultiSpanCellTableUI());

Класс MultiSpanCellTableUI реализует метод paint(), который вызывается каждую секунду.

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

Поскольку он вызывается каждую секунду, через некоторое время происходит OutOfMemoryError. Мне нужно перекрашивать ячейки только тогда, когда я что-то обновляю в ячейке и эту информацию я могу легко получить Но как я могу ограничить количество вызовов paint() на основе этой информации?

Ответы [ 2 ]

2 голосов
/ 21 декабря 2011

не знаю, зачем вам нужно

1) рисовать paint(), пожалуйста, для какого типа Компонентов в JTable's Cel l, если есть какой-то JComponent, вы должны вместо этого переопределить paintComponent()из paint()

2) плохой дизайн для выполнения нестандартного рисования в более крупном JTable

3) вы должны смотреть на Renderer, лучше было бы prepareRenderer, если вырисование с использованием некоторого цвета

4) JTable по умолчанию возвращает JLabel, там вы можете установить Icon вместо какой-либо предварительной рисования

5), возможно, поможет вам с JTable's производительность Рождественская елка приложений

1 голос
/ 21 декабря 2011

Если код не опубликован выше, я предполагаю, что вы принудительно вводите paint() для компонента JTable. Не должно быть необходимости вызывать paint() для объекта JTable. Чтобы настроить рисование ячеек, используйте 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;
    }
}
...