min*_*ins 0 java swing jtable tablecellrenderer
我在理解单元格渲染器时遇到一些困难。StretchIcon我想在 a 中使用JTable,以便列的单元格显示调整大小的徽标。StretchIcon延伸ImageIcon。
自定义渲染器:
public class IconCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
JLabel label = new JLabel();
label.setIcon( (Icon) ( new StretchIcon((Image) value) ) );
return label;
}
}
Run Code Online (Sandbox Code Playgroud)
该代码按预期工作,我对表格没有任何问题。
从本教程中,我了解到出于getTableCellRendererComponent性能原因,我应该避免创建新对象。
我不明白:
将被实例化多少次IconCellRenderer。我假设只有一次,在JTable创建时(假设表中只有一列)。
getTableCellRendererComponent会被调用多少次。我假设列中的每个单元格都调用一次,以便它可以为每个单元格返回一个JLabel带有嵌入实例的新实例StretchIcon。StretchIcon如果这是真的,那么在方法中 创建 JLabel 和 的新实例就有意义了。
需要时如何重新绘制调整大小的图标(隐藏单元格然后再次显示,或调整单元格大小)?我假设getTableCellRendererComponent根本不参与此操作,并且这完全是使用paintJLabel 的方法paint和StretchIcon.
我的理解有些不正确吗?StretchIcon在方法中创建新实例是否合法?我可以做什么来优化这个单元格渲染器,例如我可以使标签对象静态吗?
编辑:根据提供的评论和答案,我最终得到了这个单元格渲染器:
public class StretchIconRenderer extends DefaultTableCellRenderer {
private static StretchIcon stretched;
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
Image logo = (Image) value;
if (stretched == null) { stretched = new StretchIcon(logo); }
else { stretched.setImage(logo); }
setIcon(stretched);
setText(null);
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
将被实例化多少次
IconCellRenderer。我假设只有一次,在创建 JTable 时(假设表中只有一列)。
从技术上讲,它只需要创建一次,但可以根据需要多次创建。然而,一旦分配给JTable/ TableColumn,这些类将永远不会再次启动它。他们只是维护对您传递给他们的实例的引用
getTableCellRendererComponent会被调用多少次。我假设列中的每个单元格都调用一次,这样它就可以返回一个新的 JLabel 实例,并StretchIcon为每个单元格嵌入一个 的实例。如果这是真的,那么在方法中创建JLabel和的新实例就有意义了。StretchIcon
是的,这是真的,getTableCellRendererComponent将为表中的每一行调用。但是,您不需要创建组件的新实例,您可以返回为每行配置不同的相同实例。
原因是,表格简单地将结果“绘制”到其自身上,它不会以您习惯的方式“添加”组件。这通常被称为“饼干切割机”或“橡皮印章”,因为该组件仅用作模板。
需要时如何重新绘制调整大小的图标(隐藏单元格然后再次显示,或调整单元格大小)?我假设
getTableCellRendererComponent根本不参与此操作,并且这完全是使用 的 Paint 方法JLabel以及 中重新定义的 Paint 方法完成的StretchIcon。
不,这完全是通过getTableCellRendererComponent. TableModel当单元格/行/列以某种方式更新时,必须从或触发通知ColumnModel,指示表已发生更改。
该表将确定受影响的单元格并使用适当的方法重新绘制它们TableCellRenderer
简而言之。应该不需要创建JLabelinside的新实例getTableCellRendererComponent。事实上,您甚至根本不需要它JLabel,因为DefaultTableCellRenderer它是从JLabel并且您应该简单地使用它。
我不知道如何StretchIcon工作,所以您可能别无选择,只能创建一个新实例,但如果可以的话,您可能会考虑创建一个WeakHashMap键控到该Object值,它维护 的引用StretchIcon,因此您只创建一个实例每行的...
例如...
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setIcon(getStretchIconFor(value));
return this;
}
protected StreatchIcon(Object value) {
StretchIcon icon = null;
if (!cache.contains(value)) {
icon = new StretchIcon((Image) value) );
cache.put(value, icon);
}
return icon;
}
Run Code Online (Sandbox Code Playgroud)
哪里cache有一个WeakHashMap...