The source of the problem is probably in the implementation of ImageObserver
interface by JLabel
:
public boolean imageUpdate(Image img, int infoflags,
int x, int y, int w, int h) {
// Don't use getDisabledIcon, will trigger creation of icon if icon
// not set.
if (!isShowing() ||
!SwingUtilities.doesIconReferenceImage(getIcon(), img) &&
!SwingUtilities.doesIconReferenceImage(disabledIcon, img)) {
return false;
}
return super.imageUpdate(img, infoflags, x, y, w, h);
}
Here is the code for SwingUtilities.doesIconReferenceImage
:
static boolean doesIconReferenceImage(Icon icon, Image image) {
Image iconImage = (icon != null && (icon instanceof ImageIcon)) ?
((ImageIcon)icon).getImage() : null;
return (iconImage == image);
}
As you can see, if the icon is not instance of ImageIcon
the result of imageUpdate()
will be false
, without even calling into super's implementation which is actually responsible to call repaint()
on JLabel
to refresh the new frame of the animated icon. Also, returning false
means we are no longer interested in updates.
You may extend JLabel
to overcome this constraint. Here is a very simple extension of JLabel
that overrides imageUpdate()
. The actual code for this implementation of imageUpdate
is taken from Component.imageUpdate()
, just isInc
and incRate
are constants for simplicity:
public static class CustomLabel extends JLabel {
private static final boolean isInc = true;
private static final int incRate = 100;
public CustomLabel(Icon image) {
super(image);
}
@Override
public boolean imageUpdate(Image img, int infoflags, int x, int y,
int w, int h) {
int rate = -1;
if ((infoflags & (FRAMEBITS | ALLBITS)) != 0) {
rate = 0;
} else if ((infoflags & SOMEBITS) != 0) {
if (isInc) {
rate = incRate;
if (rate < 0) {
rate = 0;
}
}
}
if (rate >= 0) {
repaint(rate, 0, 0, getWidth(), getHeight());
}
return (infoflags & (ALLBITS | ABORT)) == 0;
}
}
You may plug into imageUpdate()
to add the functionality of displaying "Loading image" string while image is still loading.
I wonder what is the real reason behind the implementation of proxy for ImageIcon
. If you need synchronous image loading you can use ImageIO
API.