0

I'm using a JLabel in an attempt to draw an animated gif image onto it. I can use the constructor new JLabel(new ImageIcon(FML.class.getResource("giphy.gif"))); and that will work just fine however when I go override the paint method it just doesn't seem to want to draw it, at all. The image isn't still, it's not there! I should mention that both methods shown below work perfectly fine with a PNG but not a GIF. Am I missing something or is this a java bug? (Using java 1.8)

Edit: I've been looking around and it seems that I'm not completely off point on what I need to be doing but I'm missing something. I've seen many posts Like this one but that doesn't seem to be working in this case.

I should note that there's literally nothing else going on in the class, it's a simple JPanel.

    import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FML {

    public static void main(String[] args) {
        new FML();
    }

    public FML() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().setLayout(new FlowLayout());
                frame.getContentPane().add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private ImageIcon animatedGif;

        public TestPane() {
            setLayout(new GridBagLayout());
            JButton btn = new JButton(new ImageIcon(FML.class.getResource("FmDxW.png")));
            btn.setSize(50, 50);
            btn.setRolloverEnabled(true);
            animatedGif = new ImageIcon(FML.class.getResource("giphy.gif"));
            btn.setRolloverIcon(animatedGif);
            add(btn);

            btn.addMouseListener(new MouseAdapter() {

                @Override
                public void mouseEntered(MouseEvent e) {
                    animatedGif.getImage().flush();
                }

            });

            //I need this
            final ImageIcon image = new ImageIcon(FML.class.getResource("giphy.gif"));

            //To render over this
            final ImageIcon image2 = new ImageIcon(FML.class.getResource("fmDxW.png"));


            //I'm not understanding why I can add the gif into the constructor but the paint method fails.
            JLabel label = new JLabel(image) {
                @Override
                public void paint(Graphics g) {
                    super.paint(g);
                    g.drawImage(image2.getImage(), 64, 64, this);
                }
            };
            //setSize because I want to be 100% sure that it's loading the correct size.
            //Removing it doesn't affect the problem at hand.
            label.setSize(64, 64);
            add(label);
        }
    }
}
Cyphereion
  • 71
  • 11
  • 1) You should not be doing I/O in a painting method. 2) Custom painting (when required) is done by overriding paintComponent(...). 3) There is no need for custom painting, just add an Icon to the JLabel. 4) Don't use setSize(...) on the label. This implies you are using a null layout. Don't use null layouts. Swing was designed to be used with layout managers. Read the [Swing tutorial](http://docs.oracle.com/javase/tutorial/uiswing/TOC.html) for Swing basics. There are sections on using Icons and custom painting. – camickr Sep 12 '17 at 03:39
  • This is just testing code, I would never be using IO on production code. That being said, I do need custom painting in my specific implementation. Even though, I tried moving the IO out of the render loop because just maybe that was the issue but no dice. Problem still exists. -edit- Again, This is test code, I know how to use layout managers and custom painting isn't anything complicated. I get the feeling I'm just missing something specific. – Cyphereion Sep 12 '17 at 03:42
  • If you know how to use layout managers and do custom painting then you shouldn't have a problem and why are you overriding paint()?. But apparently you do have a problem. I have no idea why you are extending JLabel for custom painting of simply trying to draw an image. A JLabel will do this for you without any customization. All the code I see posted implies you don't understand the basics of Swing. Post a proper [mcve] that demonstrates the problem using proper Swing techniques. – camickr Sep 12 '17 at 03:52
  • There, I've included the entire class and added comments to help explain what I'm trying to do. – Cyphereion Sep 12 '17 at 04:09

1 Answers1

0
g.drawImage(image2.getImage(), 64, 64, this);

Assuming the size of your image is 64, why are you trying to draw the second image outside the bounds of the label? When I change the location to (0, 0) the gif paints fine for me (but I'm not using an animated gif).

both methods shown below work perfectly fine with a PNG but not a GIF.

I don't see how for the reason I gave above. In any case, did you try it with a normal gif?

This is a reason why you should not be trying to manage the painting yourself since now you need to worry about location and hardcoding a location is not a good practice. Let your layout manager do this for you.

Again, why are you doing this. Why are you trying to override paint method to draw a second image?

Instead you should be doing something like:

  1. Drawing both images in the paintComponent() method
  2. Use a panel with an OverlayLayout, Then you can stack the two labels on top of one another.
  3. You can even set the layout manager of the layout to something like a GridBagLayout and then when you add a JLabel to the label it will automatically be centered.

//setSize because I want to be 100% sure that it's loading the correct size.

You said you know how layout managers work. Well if you do then you know that this statement will do nothing since the layout manager will override any value you set, so using code like this wrong and shows a basic lack of understanding and should not be included in an MCVE since the point of the MCVE` is to simplify the problem as much as possible.

camickr
  • 321,443
  • 19
  • 166
  • 288