我很难理解细胞渲染器。我想在JTable
中使用StretchIcon
,以便列的单元格显示已调整大小的徽标。 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;
}
}
此代码可以正常工作,我对该表没有任何问题。
从这个tutorial,我了解到我应该避免在getTableCellRendererComponent
中出于性能原因而创建新对象。
我不明白:
将IconCellRenderer
实例化多少次。我只假设一次,创建JTable
时(假设表中只有一列)。
getTableCellRendererComponent
将被调用多少次。我假设列中的每个单元格都有一次,这样它就可以为每个单元格返回一个JLabel
的新实例,其中包含StretchIcon
的嵌入实例。如果这是真的,那么在方法中创建JLabel和StretchIcon
的新实例是有意义的。
如何在需要时重新绘制已调整大小的图标(隐藏单元格然后再次显示,或单元格调整大小)?我假设此操作中根本没有涉及getTableCellRendererComponent
,这完全是使用JLabel的paint
方法和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;
}
}
答案 0 :(得分:4)
IconCellRenderer
将被实例化多少次。我只假设一次,当创建JTable时(假设表中只有一列)。
从技术上讲,它只需要创建一次,但可以根据需要随时创建。但是,一旦分配给JTable
/ TableColumn
,这些类将永远不会再次启动它。它们只保留对传递它们的实例的引用
getTableCellRendererComponent
将被调用多少次。我假设列中的每个单元格都有一次,这样它就可以为每个单元格返回一个新的JLabel实例,其中包含StretchIcon
的嵌入实例。如果这是真的,那么在方法中创建JLabel
和StretchIcon
的新实例是有意义的。
是的,这是真的,将为表中的每一行调用getTableCellRendererComponent
。但是,您不需要创建新的组件实例,您可以为每行返回不同配置的相同实例。
原因是,表格简单"油漆"结果本身,它没有"添加"以您习惯的方式使用组件。这通常被称为"千篇一律"或者"橡皮图章",因为该组件仅用作模板。
如何在需要时重新绘制已调整大小的图标(隐藏单元格然后再次显示,或单元格调整大小)?我假设此操作中根本没有涉及
getTableCellRendererComponent
,这完全是使用JLabel
的paint方法和StretchIcon
中重新定义的paint方法完成的。
不,这完全是通过getTableCellRendererComponent
完成的。当以某种方式更新单元格/行/列时,必须从TableModel
或ColumnModel
触发通知,该通知会指示表已发生更改。
该表将使用适当的TableCellRenderer
简而言之。不需要在JLabel
内创建getTableCellRendererComponent
的新实例。事实上,你根本不需要JLabel
,因为DefaultTableCellRenderer
来自JLabel
,你应该只使用它。
我不知道StretchIcon
是如何工作的,所以你可能别无选择,只能创建一个新实例,但如果可以,你可以考虑创建一个WeakHashMap
键入{ {1}}值,它维护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;
}
是cache
...