Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display moving image in Java Swing

Tags:

java

image

swing

I'm trying to display a high-width image in Java Swing (say 2000x100, like a heart rate strip). I need to show only a window of 500 width while it is slightly moving towards left. My current code (a bit complicated, it also has unnecessary animations) does it, but the feature I need to add is: The end of image should be concatenated with the beginning of the image. So it always repeats showing over and over.

In short, I need to join the two ends of image! How can I do that?

enter image description here

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SlidingAnimation {

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

    public SlidingAnimation() {
        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);
                JPanel j = new JPanel();
                j.add(new AnimatedBar(true));
                frame.add(j);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

class AnimatedBar extends JPanel {

    private BufferedImage img;

    private Timer timer;
    private long startTime = -1;
    private int playTime = 4000;
    private int window = 500;
    private int moveX=0;
    public static boolean keepRunning=true;

    private float progress;

    public AnimatedBar(boolean x) {
        try {
            if(x)
                img = ImageIO.read(new File("strip2.jpg"));
            else
                img=null;
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        if(x){
            timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (startTime == -1) {
                        startTime = System.currentTimeMillis();
                    } else {
                        long currentTime = System.currentTimeMillis();
                        long diff = currentTime - startTime;

                        if (diff >= playTime) {
                            diff = 0;
                            startTime = -1;
                        }
                        progress = diff / (float) playTime;
                    }

                    repaint();
                }
            });
            timer.start();
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return img == null ? new Dimension(50, 50) : new Dimension(img.getWidth()/3, img.getHeight());
    }

    protected BufferedImage generateImage() {

        BufferedImage buffer = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = buffer.createGraphics();
        g2d.setBackground(new Color(0, 0, 0, 0));
        g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
        //            g2d.drawImage(img, 500, 0, this);
        g2d.drawImage(img,0,0,500,100,(moveX++),0,window+moveX,100,this);


        float startAt = progress- 0.05f;
        float endAt = progress + 0.05f;

        if (endAt <= 0.1f) {
            startAt = 0;
            endAt = Math.max(0.1f, progress);
        } else if (endAt >= 1f) {
            endAt = 1f;
            startAt = progress;
        }

        LinearGradientPaint lgp = new LinearGradientPaint(
                new Point2D.Float(0, 0),
                new Point2D.Float(img.getWidth(), 0),
                new float[]{startAt, endAt},
                new Color[]{new Color(0, 0, 0, 0), Color.RED});

        g2d.setPaint(lgp);

        g2d.setComposite(AlphaComposite.DstOut.derive(1f));
        g2d.fill(new Rectangle(0, 0, img.getWidth(), img.getHeight()));
        g2d.dispose();

        return buffer;

    }

    public void setImg(BufferedImage img) {
        this.img = img;
    }

    @Override
    protected void paintComponent(Graphics g) {
        if(keepRunning==false){
            img=null;
        }
        else{
            try {
                img = ImageIO.read(new File("strip2.jpg"));
            } catch (IOException e) {
            }
        }
            super.paintComponent(g);
            if (img != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int y = (getHeight() - img.getHeight()) / 2;
                int x = (getWidth() - img.getWidth()/3) / 2;
                g2d.drawImage(generateImage(), x, y, this);

                g2d.dispose();
        }
    }

}
like image 363
Tina J Avatar asked Dec 15 '22 19:12

Tina J


1 Answers

To join the ends, paint the image twice as seen in this answer. The first paint would be the end of the image. The second paint would be the start of the image, offset by the width the end goes to.

E.G.

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

import java.net.URL;
import javax.imageio.ImageIO;

public class HeartBeat {

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://i.stack.imgur.com/i8UJD.jpg");
        final BufferedImage bi = ImageIO.read(url);
        Runnable r = new Runnable() {

            @Override
            public void run() {
                final BufferedImage canvas = new BufferedImage(
                        bi.getWidth(), bi.getHeight(),
                        BufferedImage.TYPE_INT_RGB);
                final JLabel animationLabel = new JLabel(new ImageIcon(canvas));
                ActionListener animator = new ActionListener() {

                    int x = 0;

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        Graphics2D g = canvas.createGraphics();

                        // paint last part of image in left of canvas
                        g.drawImage(bi, x, 0, null);
                        // paint first part of image immediately to the right
                        g.drawImage(bi, x + bi.getWidth(), 0, null);

                        // reset x to prevent hitting integer overflow
                        if (x%bi.getWidth()==0) x = 0;

                        g.dispose();
                        animationLabel.repaint();
                        x--;
                    }
                };
                Timer timer = new Timer(40, animator);
                timer.start();
                JOptionPane.showMessageDialog(null, animationLabel);
                timer.stop();
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}
like image 156
Andrew Thompson Avatar answered Jan 16 '23 08:01

Andrew Thompson