0

Hey all I am wondering if I can fix my animation issue.

Currently it does animate just fine but with one issue - it seems to leave training images behind as it animates.

enter image description here

This is my code I am using:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.io.File;
import java.io.FileInputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.io.*;

@SuppressWarnings("serial")
public class Display extends JFrame {
    private static JPanel container = new JPanel();
    JLabel insidePIV = new JLabel();

    public static void main(String[] args) throws IOException {
        Display blah = new Display();
    }

    public void addListeners() {
        final Point offset = new Point();
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(final MouseEvent e) {
                offset.setLocation(e.getPoint());
            }
        });
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(final MouseEvent e) {
                setLocation(e.getXOnScreen() - offset.x, e.getYOnScreen() - offset.y);
            }
        });
    }

    public Display() throws IOException {
        JLabel outsidePIV = new JLabel(new ImageIcon(ImageIO.read(new File("c:/temp/pivReaderAlone.png"))));
        MyJLabel antialias = new MyJLabel(
                "<html><div style='text-align: center;'>Please insert your card into the reader.</div></html>");

        antialias.setFont(new Font("Segoe UI", Font.BOLD, 10));
        antialias.setBounds(13, 223, 170, 240);
        container.setLayout(new BorderLayout());
        container.setBackground(new Color(0, 0, 0, 0));

        container.add(antialias, BorderLayout.CENTER);
        container.add(outsidePIV, BorderLayout.CENTER);

        JButton p = new JButton();
        p.setText("Animate");
        p.setBounds(30, 100, 120, 20);

        outsidePIV.add(p, BorderLayout.CENTER);

        p.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    File file = new File("c:/temp/pivbatman.gif");
                    Image image = Toolkit.getDefaultToolkit()
                            .createImage(org.apache.commons.io.IOUtils.toByteArray(new FileInputStream(file)));
                    ImageIcon icon = new ImageIcon(image);
                    outsidePIV.setDoubleBuffered(true);
                    outsidePIV.setIcon(icon);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        });

        addListeners();

        this.setTitle("PIV");
        this.setSize(190, 390);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setAlwaysOnTop(true);
        this.setUndecorated(true);
        this.setBackground(new Color(0, 0, 0, 0));
        this.setContentPane(container);
        this.setVisible(true);
        this.setResizable(false);
    }

    public class MyJLabel extends JLabel {
        public MyJLabel(String str) {
            super(str);
        }

        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

            super.paint(g);
        }
    }
}

If anyone can help me with this error then please do - been trying to fix it for hours now...

UPDATE

public static void main(String[] args) throws IOException {     
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                Display blah = new Display();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });
}
StealthRT
  • 10,108
  • 40
  • 183
  • 342
  • What does “as it animates” mean? Are you referring to dragging the window around the screen? Note that `SwingUtilities.invokeLater` is not enough; you also have to remove `static` from your declaration of `container`, to make sure it is also initialized in the proper thread. – VGR Nov 07 '19 at 20:50
  • @VGR As in when each frame of the animation is displayed. Each seems to stay on the screen as it animates as seen in my first posted image in my OP. – StealthRT Nov 07 '19 at 22:24
  • What animation? Your code doesn’t seem to animate anything that I can see. – VGR Nov 07 '19 at 23:59
  • @VGR it's an animated gif.... – StealthRT Nov 08 '19 at 00:00
  • Ah, now I can reproduce the problem. – VGR Nov 08 '19 at 00:04
  • 1
    Don't know if it will help but: 1. why use 3rd party I/O. You can just pass the file name as a String to the ImageIcon or use ImageIO to read the file. 2. there is no need to set double buffered. Swing components are double buffered by default 3. try the code first without the custom rendering hints. The main idea of the suggests is to use the default JDK classes and setting first to test something. I have never had a problem with animated gifs using JDK8 on Windows 7. It also makes it easier to post code. I can't test your code because I don't have IOUtils. – camickr Nov 08 '19 at 01:05
  • 1) `File file = new File("c:/temp/pivbatman.gif");` Upload that GIF, then in the source code, load it from the URL. (To make a [mre]) What relevance does the PNG have to the problem? Try to reproduce it without, then remove that code. Also remove dependency on any 3rd party classes like `org.apache...`. 2) `public void paint(Graphics g)` The correct method for any `JComponent` (or anything that extends it) is `paintComponent`.. – Andrew Thompson Nov 08 '19 at 03:27
  • I actually changed all the ImageIcon constructors to use ImageIcon(String) when I was testing this. Aside from making the code cleaner, it didn’t make a difference. The label is not cleared when each successive frame of an animated GIF is painted. – VGR Nov 08 '19 at 03:32
  • Possible answer and solution to this: https://stackoverflow.com/questions/26330550/java-gif-animation-not-repainting-correctly – VGR Mar 05 '20 at 18:55

1 Answers1

1

Render images on Java Swing is trick, java has a main UI Thread called AWT that is not concurrent. It´s a good practice to use the method invokeLater from SwingUtilities class.

SwingUtilities.invokeLater takes a Runnable and invokes it in the UI thread later.

The syntax is:

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        //some code that render in the UI here. 
    }
});
Edu Costa
  • 1,414
  • 13
  • 13
  • I updated my OP but it doesnt seem to help. It still keeps the last picture(s) when animating. – StealthRT Nov 07 '19 at 18:57
  • Maybe you face a problem due to the size of the images. Your example is running look https://www.loom.com/share/85dfbc2eaed5413f87ee6e7915460f8a – Edu Costa Nov 08 '19 at 11:45