I used to write that this
JLabel label=new JLable(URL);
frame.getContentPane().add(label);
and it works with animated gif image
however , when I want use a imageProxy to load the gif form the internet it doesn't work.
my imageProxy is this
public class ImageProxy implements Icon{
ImageIcon imageIcon;
URL imageURL;
Thread retrievalThread;
boolean retrieving =false;
public ImageProxy(URL url){
imageURL = url;
}
public int getIconHeight() {skip}
public int getIconWidth() {skip}
@Override
public void paintIcon(final Component c, Graphics g, int x, int y) {
System.out.println("paint");
if(imageIcon !=null){
imageIcon.paintIcon(c, g, x, y);
}else{
g.drawString("Loading image", x+10, y+80);
if(!retrieving){
retrieving =true;
retrievalThread = new Thread(new Runnable(){
public void run(){
try{
imageIcon = new ImageIcon(imageURL);
c.repaint();
}catch(Exception e){
e.printStackTrace();
}
}
});
retrievalThread.start();
}
}
}
}
it can success to load the image but it won't auto to refresh it image I have to chage to image by zoom the frame, every time i zoom it chage one picture
I read the document , it said that , in other to display a gif i need to setImageObsever i tried , doesn't work. and the imageIcon normal work with no proxy print null by getImageObserver
I also tried to read the souce code but i did not really understand.
Pleas help me ,thank you.
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.