gpt4 book ai didi

java - 设置单独行高时 JTable 内存泄漏

转载 作者:行者123 更新时间:2023-12-01 16:41:21 25 4
gpt4 key购买 nike

我需要在 JTable 中显示多行内容。实际内容是在自定义模型中维护的对象集合,该模型扩展了 DefaultTableModel 并通过重写 getValueAt() 动态生成单元格内容。

为了拥有多行内容,我实现了一个自定义TableCellRenderer:

private class MultiLineCellRenderer extends JTextArea implements TableCellRenderer {
public MultiLineCellRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
setBorder(new EmptyBorder(-1, 2, -1, 2));
setRows(1);
}

public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
String text = value == null ? "" : value.toString();
if (!getText().equals(text)) {
setText(text);

int newHeight = table.getRowHeight() * getLineCount();
if (table.getRowHeight(row) != newHeight)
table.setRowHeight(row, newHeight);
}

if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}

return this;
}
}

现在,如果我用几百行填充表(列数为 2),我会看到 AWT 工作线程开始耗尽一个 CPU 核心。同时,内存消耗从约 100 MB 增加到十倍甚至更多。即使应用程序实际上没有执行任何操作(后台没有加载数据,没有用户交互)并且仅当我清除表从中获取其内容的集合时才会停止,这种情况也会发生。

通过注释掉选定的代码部分,我已确定这些行是罪魁祸首:

            int newHeight = table.getRowHeight() * getLineCount();
if (table.getRowHeight(row) != newHeight)
table.setRowHeight(row, newHeight);

如果我注释掉此部分,所有表格行都具有相同的高度(1 行文本),但内存消耗保持在约 100 MB 左右。

如果我通过一次调用 table.setRowHeight(row, 32) 替换这些行,即使用固定值,内存消耗将开始无限期地再次上升。

以下修改有效,但代价是所有行具有相同的高度:

            int newHeight = getRowHeight() * getLineCount();
if (table.getRowHeight() < newHeight)
table.setRowHeight(newHeight);

底线:在 JTable 中设置单独的行高度似乎会造成大量内存泄漏。我是否做错了什么,或者我遇到了实际的错误?在后一种情况下,是否有任何已知的修复/解决方法?

最佳答案

设置行高会触发重绘,从而触发对渲染器的另一次调用。因此,只有当行高与当前行高不同时才设置行高,以避免无限循环,这一点很重要。这就是当您无条件调用 setRowHeight() 时发生的情况,即使使用固定值也是如此。

第二个问题是每行包含两个单元格,它们可能具有不同的高度。上面的代码将设置行高以匹配当前正在呈现的单元格。当该行的另一个单元格被渲染并具有不同的高度时,行高会再次更改。这将触发重绘,也是该行中第一列的重绘。由于这将导致另一个高度变化,因此再次出现无限循环。

证明:以下代码解决了这个问题:

            int newHeight = table.getRowHeight() * getLineCount();
if (table.getRowHeight(row) < newHeight)
table.setRowHeight(row, newHeight);

现在行高只会增加,而不会减少,从而打破了无限循环。副作用:如果单元格内容发生更改并且现在占用的行数比以前少,则行高不会更改以反射(reflect)这一点。

底线:渲染具有多行单元格的 JTable 并不简单,并且 SO 有相当多的错误示例。我发现的唯一有效示例(感谢另一篇 SO 帖子)位于 https://www.javaspecialists.eu/archive/Issue106.html .

他们的解决方案是在渲染器内部存储单元高度(尽管这也可以在表格模型中完成,以最适合您的实现为准)。计算单元格的高度时,将其存储,然后获取该行中任何单元格的最大高度并使用它。另外,请确保仅在行高与当前行高不同时才设置行高。

这解决了内存泄漏/处理器消耗问题,此外还最终为我提供了如何正确计算单元高度的工作示例。

关于java - 设置单独行高时 JTable 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61856679/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com