组件可见时的java事件

标签 java swing events jscrollpane componentlistener

我有一个 JScrollPane 环绕着一个 JPanel,它可能包含数百个显示缩略图图像的 JLabel(每个 JLabel 一个缩略图)。出于内存原因,我不想构建所有缩略图。我只想为可见的 JLabel 构建缩略图,并在它们的 JLabel 变得不可见时删除缩略图。当用户滚动 JPanel 时,它们变得可见/不可见。我试图通过使用 ComponentListener 来实现加载/卸载缩略图:

addComponentListener( new ComponentAdapter() {

    @Override
    public void componentShown( ComponentEvent e ) {
        setIcon( new ImageIcon( getThumb() ) );
    }

    @Override
    public void componentHidden( ComponentEvent e ) {
        setIcon( null );
    }
});

但这行不通。 JLabel 始终为空。我可以使用滚动事件并计算应该加载哪些缩略图,但在我这样做之前我想知道是否有更简单的解决方案。

最佳答案

“可见”属性并不意味着“在屏幕上”可见。它仅指示组件本身是否要显示。由于组件在默认情况下是可见的,并且只有在属性更改时才会通知监听器,因此永远不会通知监听器。

据我所知,当组件进入显示器的可见区域时,没有专门的事件通知组件。另请注意,在标签上设置图标可能会改变其首选大小,从而破坏整个布局。这可以通过手动为标签提供固定的首选大小来解决(对于缩略图来说应该很简单)。

一种懒惰的方法是覆盖标签上的 paintComponent 并检查是否需要在 paintComponent 中加载拇指:

 protected void paintComponent(Graphics g) {
     if (getIcon() == null) {
         // create thumbnail
     }
     super.paintComponent(g);
 }

这不是最佳方法,因为您的代码将在 Swings 事件分派(dispatch)线程内运行。这意味着加载缩略图的任何延迟都会阻止您的 UI 呈现。

IMO 更明智的方法是只请求加载缩略图并将实际加载推迟到后台线程。当该线程完成加载时,它可以使用 SwingUtilities.invoke(或 invokeLater)更新标签(如果我没记错的话,它会自动触发重绘)。

效果是滚动的标签短暂显示为空,然后在拇指可用时立即更新。

关于组件可见时的java事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35232007/

相关文章:

Java jar 文件无法识别从 gradle 添加的外部库

java - 如何防止 substr() 上出现 NullPointerException?

java - 为什么 Java Graphics2D 'drawString' 停止 repaint()?

java - 是否有 Swing hack 来查询或设置窗口的 Z 顺序?

javascript - 如何使用 Angular 事件处理程序引用输入元素的值

Java反射-从哪里继承的方法?

java - Eclipse 文件夹,其中包含要编译/执行 (bin) 目录的 Java 项目中的资源

java - 触发事件时面板从 Box 中消失

Java setOnAction 订阅抛出异常的事件

javascript - 您应该如何从 Node 中的 EventEmitter 继承?