仅当 JList 项可见时才加载某些内容

发布于 2024-08-09 22:11:43 字数 1477 浏览 3 评论 0原文

我正在实现一个填充有很多元素的 Jlist。每个元素对应一个图像,因此我想在列表的每一行中显示它们的调整大小的预览。我已经实现了一个扩展 Jlabel 的自定义 ImageCellRenderer ,并且在 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());

    }

我认为列表中只有某个项目是可见的,调用单元格渲染器,但我看到当我将页面对象添加到列表模型时,所有缩略图都是创建的。我尝试加载项目,然后在 JList 中设置模型,或者先设置模型,然后开始附加项目,但结果是相同的。 有没有什么方法可以仅在必要时加载数据,或者我是否需要创建一个自定义控件,例如 JScrollPanel,其中包含堆叠的项目,在其中我自己检查每个元素的可见性?

谢谢

i'm implementing a Jlist populated with a lot of elements. Each element corresponds to a image so i'd like to show a resized preview of them inside each row of the list. I've implemented a custom ImageCellRenderer extending the Jlabel and on getListCellRendererComponent i create the thumbnail if there'snt any for that element. Each row corresponds to a Page class where i store the path of the image and the icon applied to the JLabel. Each Page object is put inside a DefaultListModel to populate the JList.
The render code is something like this:

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

    }

I was thinking that only a certain item is visibile in the List the cell renderer is called but i'm seeing that all the thumnails are created when i add the Page object to the list model. I've tried to load the items and after set the model in the JList or set the model first and after starting appending the items but the results are the same.
Is there any way to load the data only when necessary or do i need to create a custom control like a JScrollPanel with stacked items inside where i check myself the visibility of each elements?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青瓷清茶倾城歌 2024-08-16 22:11:43

我相信 JList 循环遍历所有项目并调用渲染器以确定列表的首选大小。

您可以使用 setPrototypeCellValue(...) 方法来防止这种情况。当然,渲染器仍然会被滚动窗格中可见的所有项目调用。

I believe the JList loops through all the items and invokes the renderer in order to determine the preferred size of the list.

You might be able to prevent this by using the setPrototypeCellValue(...) method. Of course the renderer will still be invoked for all items visible in the scroll pane.

乞讨 2024-08-16 22:11:43

罪魁祸首似乎是其 updateLayoutState() 中的 BasicListUI。在绘画操作期间,当设置了 updateLayoutStateNeeded 标志时(并且在似乎每次属性更改之后设置,以及当在 dataModel 中添加和删除间隔时)。在每个单元格上,它将调用 getListCellRendererComponent 方法并导致您加载图标。如果您在 JList 实例上设置 fixedCellHeightfixedCellWidth 字段,则可以阻止这种情况发生。

您可以尝试使用两个公共方法设置固定的高度和宽度:

  • setFixedCellHeight(int)
  • setFixedCellWidth(int)

顺便说一句:一般来说,从文件加载图标如果在事件调度线程中执行,系统可能会很慢并导致 GUI 感觉迟缓。对于大图像来说,这通常是一个更大的问题,因为加载文件可能需要时间。如果还没有的话,您可能想考虑在单独的线程中加载图标。这可以通过预先加载共享的“图标不可用图像”来完成,当您的 Page 被查询图标时,如果特定于页面的图标为空,您可以触发加载所需文件的,然后返回“图标不可用图像”,加载 Page 后,将其分配给 Page 实例并触发重绘。只是一个想法。

The culprit appears to be the BasicListUI in its updateLayoutState(). During a painting operation, it will iterate over each of the elements in your dataModel when the updateLayoutStateNeeded flag is set (and that is set after seemingly every property change, as well as when intervals are added and removed from the dataModel). On each of the cells, it will invoke the getListCellRendererComponent method and cause you to load your icon. You can stop this from happening if you set the fixedCellHeight and fixedCellWidth fields on your JList instance.

You can try to set the fixed height and width with the two public methods:

  • setFixedCellHeight(int)
  • setFixedCellWidth(int)

As an aside: in general, loading icons from the file system can be slow and cause your GUI to feel sluggish if performed in the Event Dispatch Thread. This is usually more a problem with large images, where loading the file can take time. You might want to, if you haven't already, consider loading the icons in a separate thread. This could be done by having a shared 'icon unavailable image' that you load up front, and when your Page is queried for an icon, if the page-specific icon is null, you can trigger the loading of the wanted file, and then return the 'icon unavailable image', and once the Page has loaded, assign it to the Page instance and trigger a repaint. Just a thought.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文