user4108586
user4108586

Reputation:

Using Swing Timer to update BufferedImage on GUI

I've been trying to update a BufferedImage that is inserted to a GUI by using the Swing Timer. Initially I created the ImageIcon using the BufferedImage I get through a controller instance and then added it to JLabel (field). The current image was then shown on the GUI. Here a code snippet from the initial code inside the GUI class.

JLabel field;
ImageIcon icon;
BufferedImage image = this.controller.getCameraImage();
icon = new ImageIcon(image);
field= new JLabel (icon);

Now I’m trying to get a BufferedImage every x seconds . For this purpose I used the Swing Timer class but unfortunately I haven’t been able to suceed. I created the following class with an ActionListener, so that every 3 seconds a new image is retrieved with the method getCameraImage.

Here the UpdateImage with the ActionListener class:

public class UpdateImage {

private JLabel label;
private Timer timer;
private Controller controller;
private int delay = 3000; // every 3 seconds
private ImageIcon icon;
private BufferedImage image;


public UpdateImage(Controller controller) throws Exception {
    this.controller = controller;

    ActionListener action = new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent event) {
            try {
                System.out.println("image update");
                label = new JLabel();
                image = controller.getCameraImage();
                label.setIcon(new ImageIcon(image));
            } catch (CallError | InterruptedException e) {

                e.printStackTrace();
            }

        }

    };

    timer = new Timer(delay, action);
    timer.setInitialDelay(0);
    timer.start();

}



public JLabel getLabel() {
    return label;
}

}

After the BufferedImage has been set as an ImageIcon I retrieve it with the getLabel method. And then add this component to the GUI.

public class GUI{
UpdateImage update;

 //more code

JLabel field;
SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                try {
                new UpdateImage(controller);
                } catch (Exception e) {

                    e.printStackTrace();
                }
            }
        });
}
field = update.getLabel( );


//more code

}

The String "image update" shows up as desired every 3 seconds on the console. But the image won’t be diplayed on the GUI.

I'd really appreciate if someone could help me out on that by giving me some sort of hint or pointing out what I'm doing wrong.

Upvotes: 1

Views: 498

Answers (1)

camickr
camickr

Reputation: 324108

The image is cached when you use an ImageIcon with the same file name. You need to force the image to be reloaded:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;
import java.net.*;

public class ImageReload extends JPanel implements ActionListener
{
    JLabel timeLabel;
    JLabel imageLabel;
    ImageIcon icon = new ImageIcon("timeLabel.jpg");

    public ImageReload()
    {
        setLayout( new BorderLayout() );

        timeLabel = new JLabel( new Date().toString() );
        imageLabel = new JLabel( timeLabel.getText() );

        add(timeLabel, BorderLayout.NORTH);
        add(imageLabel, BorderLayout.SOUTH);

        javax.swing.Timer timer = new javax.swing.Timer(1000, this);
        timer.start();
    }

    public void actionPerformed(ActionEvent e)
    {
        timeLabel.setText( new Date().toString() );

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    String imageName = "timeLabel.jpg";
                    BufferedImage image = ScreenImage.createImage(timeLabel);
                    ScreenImage.writeImage(image, imageName);

                    //  This works using ImageIO

                    imageLabel.setIcon( new ImageIcon(ImageIO.read( new File(imageName) ) ) );

                    //  Or you can flush the image
/*
                    ImageIcon icon = new ImageIcon(imageName);
                    icon.getImage().flush();
                    imageLabel.setIcon( icon );
*/
                    imageLabel.setText("");
                }
                catch(Exception e)
                {
                    System.out.println( e );
                }
            }
        });
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new ImageReload() );
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

Edit:

You will also need the Screen Image class to execute this code.

Upvotes: 3

Related Questions