0

A gif that I tried to put into a JPanel isn't showing up after clicking the button that triggers it until I resize the window. When it does show up, it does not fit the JPanel and is not animated. I looked at several posts that dealt with this but I don't understand how to use them in my case.

/*
 * Author: Raymo111
 * Date: 13/04/2018
 * Description: Wishes happy birthday to a special someone
 */

//Imports java GUI classes
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

// Main class with JFrame and ActionListener enabled
public class Happy_Birthday_GUI extends JFrame implements ActionListener {

    // Class variables
    private static JButton startButton = new JButton("CLICK TO START");
    private static JPanel startPanel = new JPanel(), gifPanel = new JPanel();
    private static Color blue = new Color(126, 192, 238), pink = new Color(255, 192, 203);
    private static GridLayout grid1 = new GridLayout(1, 1);

    // Constructor
    public Happy_Birthday_GUI() {

        // Initial screen
        startButton.addActionListener(this);
        startButton.setFont(new Font("Comic Sans MS", Font.PLAIN, 50));
        startPanel.setLayout(grid1);
        startPanel.add(startButton);
        startPanel.setBorder(BorderFactory.createLineBorder(blue, 100));
        startButton.setBackground(pink);
        getContentPane().add(startPanel);

        // Sets title, size, layout (grid 1x1), and location of GUI window (center)
        setTitle("Happy Birthday from Dolphin");
        setSize(840, 840);
        setLayout(grid1);
        setLocationRelativeTo(null);
        setVisible(true);

    }

    // Main method
    public static void main(String[] args) {
        new Happy_Birthday_GUI();
    }

    // Action Performed method
    public void actionPerformed(ActionEvent event) {

        // Proceed to gif and song
        if (startButton == event.getSource()) {
            getContentPane().removeAll();
            BufferedImage dolphin;
            gifPanel.setLayout(grid1);
            gifPanel.setBorder(BorderFactory.createLineBorder(pink, 100));
            try {
                dolphin = ImageIO.read(new File("C:\\Users\\raymo\\Pictures\\dolphin.gif"));
                JLabel gifLabel = new JLabel(new ImageIcon(dolphin));
                gifPanel.add(gifLabel);
            } catch (IOException e) {
                e.printStackTrace();
            }
            getContentPane().add(gifPanel);
        }
    }

}

Here is dolphin.gif. It's cute.

Dolphin.gif


How do I get it to show up immediately after clicking the start button as an animated gif that fits the JPanel? Thanks in advance.

Raymo111
  • 514
  • 8
  • 24
  • Don't use `ImageIO.read` to read animated Gif's, it won't work. Instead you need to use `ImageIcon` – MadProgrammer Apr 14 '18 at 00:23
  • @MadProgrammer How do I use that? – Raymo111 Apr 14 '18 at 00:23
  • ... You could start by reading the [JavaDocs](https://docs.oracle.com/javase/8/docs/api/javax/swing/ImageIcon.html) or looking at the [tutorials](https://docs.oracle.com/javase/tutorial/uiswing/components/icon.html) – MadProgrammer Apr 14 '18 at 00:25
  • @MadProgrammer Umm... okay, but how do I get it to refresh immediately and get it to fill the panel? – Raymo111 Apr 14 '18 at 00:26
  • @MadProgrammer Thanks! The gif worked. Now for resizing and immediately showing it? – Raymo111 Apr 14 '18 at 00:29
  • Okay, do you understand what a animated gif actually is? It's a series of images stored in a single file - you will need to rescale each image, either by converting the image or extracting each frame and displaying it yourself - this is not a trivial process - [for example](https://stackoverflow.com/questions/22188940/gif-image-doesnt-moves-on-adding-it-to-the-jtabbed-pane/22190844#22190844), [example](https://stackoverflow.com/questions/26330550/java-gif-animation-not-repainting-correctly/26331052#26331052) – MadProgrammer Apr 14 '18 at 00:30
  • and [example](https://stackoverflow.com/questions/18117283/mirroring-animated-gif-on-load-in-java-imageicon/18117326#18117326) – MadProgrammer Apr 14 '18 at 00:31
  • @MadProgrammer Yikes! I think I'll just rescale it myself. – Raymo111 Apr 14 '18 at 00:36
  • @MadProgrammer, `Don't use ImageIO.read to read animated Gif's` - cool, didn't know this. I've always just used ImageIcon(...) to read the gif so its always worked by chance. `you will need to rescale each image,` - Darryl's StretchIcon (link in my answer) seems to handle this ok. – camickr Apr 14 '18 at 00:37
  • @camickr The stretchIcon thing I don't know how to use, and the revalidate + repaint thing gives me a blank grey window. – Raymo111 Apr 14 '18 at 00:39
  • @Raymo111 `StretchyIcon` extends `ImageIcon` ... the operation is basically the same – MadProgrammer Apr 14 '18 at 00:43
  • @camickr You can wrap the `BufferedImage` image in a `ImageIcon` (from memory) and it will begin to work, but the `BufferedImage` itself won't animate :P – MadProgrammer Apr 14 '18 at 00:44

3 Answers3

2

BufferedImage doesn't support painting animated Gifs, instead, you'll need to make use of Image (or preferably, ImageIcon).

This could then be applied directly to a JLabel, which will perform the animation operation itself.

animated gif that fits he JPanel?

Okay, that's a much more complex problem. One approach would be to convert the Gif to the required size, but needless to say, that's very, very complex.

A simpler solution might be to use a AffineTransform and scale the image to meet the requirements of the component itself. This would require a custom component, capable of calculating the scale and painting each frame of the image.

Luckily for you, JPanel is an ImageObserver, this means it's capable of painting the gif animation

Stretchy

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private ImageIcon image;

        public TestPane() {
            image = new ImageIcon("/Users/swhitehead/Downloads/NbENe.gif");
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600, 600);
        }

        @Override
        protected void paintComponent(Graphics g) {
            int imageWidth = image.getIconWidth();
            int imageHeight = image.getIconHeight();

            if (imageWidth == 0 || imageHeight == 0) {
                return;
            }
            double widthScale = (double)getWidth() / (double)imageWidth;
            double heightScale = (double)getHeight() / (double)imageHeight;
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.drawImage(image.getImage(), AffineTransform.getScaleInstance(widthScale, heightScale), this);
            g2d.dispose();
        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
1

I tried to put into a JPanel isn't showing up after clicking the button

When you add (or remove) components from a visible GUI the basic code is:

panel.add(...);
panel.revalidate();
panel.repaint();

The revalidate() is need to invoke the layout manager so the component is given a size.

is not animated.

Use a JLabel with an ImageIcon to display images. A JLabel will animated the gif.

When it does show up, it does not fit the JPanel and

You can try the Stretch Icon which is designed to fill the space available to the label.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Repainting is not working, and how do I use the stretch icon thing? – Raymo111 Apr 14 '18 at 00:21
  • `Repainting is not working. –` - well, why do you add the label to a panel and then the panel to the content pane? In this case you would need to revalidate() the content pane, since that is the component you are actually adding to the frame. In this case you can just use revalidate() on the JFrame. – camickr Apr 14 '18 at 00:31
  • Using either `revalidate();` or `repaint();` gives a blank screen. – Raymo111 Apr 14 '18 at 00:33
  • `gives a blank screen.` - Everything I've suggested here works fine for me, once the image was loaded using ImageIcon(...) instead of ImageIO. You changed your code incorrectly. `The stretchIcon thing I don't know how to use,` - its just like ImageIcon. Read the link. Download the class. Look at the API and pick the appropriate constructor to read the image. – camickr Apr 14 '18 at 00:43
  • The `revalidate` and `repaint` functions now work when I use @MadProgrammer 's TestPane class. – Raymo111 Apr 14 '18 at 00:53
  • It has nothing to do with his test panel. The code you posted also works when you revalidate() the frame AFTER you add the panel to the content pane. As I told you everything I suggested here works. If it doesn't work for you then you the revalidate() on the wrong component or at the wrong time. You didn't post your code so I can't guess what you are doing. Take the time to understand what you did wrong! – camickr Apr 14 '18 at 01:00
  • I know you're really good at this stuff, but please be nice and not be mean, I don't want to flag you. – Raymo111 Apr 14 '18 at 01:02
  • 1
    @Raymo111, What do you mean be mean?. You are the one ignoring my suggestions. I suggested the StretchIcon, which is as easy to use as the ImageIcon. The StretchIcon can also be used on any other component that can use an Icon like a JButton (although animated gifs only work on a JLabel). I also told you that your code is fine, you just need to add the revalidate() in the correct place. If fact I repeated it multiple times. How is that being mean? Not once in this conversation have you said "thank you" for the help. All you have done is keep asking for more help! – camickr Apr 14 '18 at 01:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/168959/discussion-between-raymo111-and-camickr). – Raymo111 Apr 14 '18 at 01:09
  • @Raymo111, In fact the last time I helped you: https://stackoverflow.com/questions/49787032/java-how-to-remove-an-existing-border-of-a-jpanel/49787049#49787049, you just deleted the question even though I gave you the answer to your question. Once again, you didn't bother to reply with a simple "thank you". even in this question you haven't "accepted" an answer even though your problem is solved! – camickr Apr 14 '18 at 01:17
  • Last time I did thank you and I only deleted the question because you and 5 other users were downvoting the question because of a bad MCVE! – Raymo111 Apr 14 '18 at 01:19
  • And did you see my last post in the [chat](https://chat.stackoverflow.com/rooms/168959/discussion-between-raymo111-and-camickr)?! – Raymo111 Apr 14 '18 at 01:20
  • @Raymo111, `Last time I did thank you` - no you didn't. See the link I provided in my last comment. `did you see my last post in the chat?` - The "thank you" should be given in the posting and you should not need to be reminded. And you still haven't "accepted" MadProgrammers answer, indicating a solution has been found. – camickr Apr 14 '18 at 01:32
  • Oh yes and to answer your original question, the MCVE is much better. – camickr Apr 14 '18 at 01:35
  • Alright. Here's why I didn't thank you. I already tried `setBorder(null)` before asking the question, then realized that my `m` and `n` variables should have been `j` and `k`. While making an MCVE, I realized that and deleted the question, by which time you and 2 other users had downvoted. If it makes you feel any better, I do appreciate, very much, you and the other users who answer my questions, and I did accept your answer. – Raymo111 Apr 14 '18 at 01:39
  • `I already tried setBorder(null) before asking the question,` - you did not state that in the question and my answer confirmed that is a valid solution. I then stated if it didn't work you had a logic error. `then realized that my m and n variables should have been j and k.` - I pointed that out before you even created a MCVE. So I suggested the logic solution as well. I also pointed out the value of creating an MCVE to simplify a problem to make sure you understand the real problem. Often when you create an MCVE you will solve the problem before you post to a forum, saving yourself time. – camickr Apr 14 '18 at 01:54
0

I ended up doing:

gifPanel.add(new TestPane());
getContentPane().add(gifPanel);
revalidate();
repaint();

using camickr's revalidate and repaint, and MadProgrammer's TestPane class, which worked very well to get the gif to animate, resize correctly and display immediately.

Raymo111
  • 514
  • 8
  • 24