我正在实现一个填充了大量元素的Jlist。每个元素对应一个图像,所以我想在列表的每一行内显示它们的大小调整预览。我实现了一个自定义 ImageCellRenderer 扩展Jlabel,并在 getListCellRendererComponent 上创建了缩略图,如果该元素没有任何内容。每行对应一个 Page 类,其中我存储图像的路径和应用于JLabel的图标。每个 Page 对象都放在 DefaultListModel 中以填充JList。 渲染代码是这样的:
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
Page page = (Page) value;
if (page.getImgIcon() == null)
{
System.out.println(String.format("Creating thumbnail of %s", page.getImgFilename()));
ImageIcon icon = new ImageIcon(page.getImgFilename());
int thumb_width = icon.getIconWidth() > icon.getIconHeight() ? 128 : ((icon.getIconWidth() * 128) / icon.getIconHeight());
int thumb_height = icon.getIconHeight() > icon.getIconWidth() ? 128 : ((icon.getIconHeight() * 128) / icon.getIconWidth());
icon.setImage(getScaledImage(icon.getImage(), thumb_width, thumb_height));
page.setImgIcon(icon);
}
setIcon(page.getImgIcon());
}
我想在List中只有某个项是可见的,而单元格渲染器被调用,但是当我将Page对象添加到列表模型时,我看到所有的thumnails都被创建了。我试图加载项目,然后在JList中设置模型或首先设置模型,并在开始附加项目后但结果是相同的。 有没有办法只在必要时加载数据,或者我是否需要创建一个自定义控件,如带有堆叠项目的JScrollPanel,我自己检查每个元素的可见性?
由于
答案 0 :(得分:3)
我相信JList遍历所有项目并调用渲染器以确定列表的首选大小。
您可以通过使用setPrototypeCellValue(...)方法来阻止这种情况。当然,仍会为滚动窗格中可见的所有项目调用渲染器。
答案 1 :(得分:1)
罪魁祸首似乎是BasicListUI
中的updateLayoutState()
。在绘制操作期间,当设置dataModel
标志时,它将迭代updateLayoutStateNeeded
中的每个元素(并且在看似每个属性更改之后设置,以及添加和删除间隔时设置)来自dataModel
)。在每个单元格上,它将调用getListCellRendererComponent
方法并导致您加载图标。如果您在JList实例上设置 fixedCellHeight
和 fixedCellWidth
字段,则可以阻止这种情况发生。
您可以尝试使用两种公共方法设置固定的高度和宽度:
setFixedCellHeight(int)
setFixedCellWidth(int)
顺便说一句:一般来说,从文件系统加载图标可能会很慢,如果在事件调度线程中执行,会导致GUI感觉迟钝。这通常是大图像的问题,加载文件可能需要一些时间。您可能希望,如果您还没有,请考虑在单独的线程中加载图标。这可以通过预先加载的共享“图标不可用图像”来完成,当您查询Page
图标时,如果页面特定图标为空,则可以触发加载所需的图像文件,然后返回'icon unavailable image',加载Page
后,将其分配给Page
实例并触发重新绘制。只是一个想法。