Updating an image contained in a JLabel – problems

Instead of creating a New Instance of the JLabel for each Image, simply use JLabel#setIcon(…) method of the JLabel to change the image.

A small sample program :

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

public class SlideShow extends JPanel
{
    private int i = 0;
    private Timer timer;
    private JLabel images = new JLabel();
    private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"),
                            UIManager.getIcon("OptionPane.errorIcon"),
                            UIManager.getIcon("OptionPane.warningIcon")};
    private ImageIcon pictures1, pictures2, pictures3, pictures4;
    private ActionListener action = new ActionListener()
    {
        public void actionPerformed(ActionEvent ae)
        {                       
            i++;
            System.out.println(i);

            if(i == 1)
            {
                pictures1 = new ImageIcon("image/caIcon.png");
                images.setIcon(icons[i - 1]);
                System.out.println("picture 1 should be displayed here");
            }
            if(i == 2)
            {
                pictures2 = new ImageIcon("image/Keyboard.png");
                images.setIcon(icons[i - 1]);   
                System.out.println("picture 2 should be displayed here");
            }
            if(i == 3)
            {
                pictures3 = new ImageIcon("image/ukIcon.png");
                images.setIcon(icons[i - 1]);
                System.out.println("picture 3 should be displayed here");  
            }
            if(i == 4)
            {
                pictures4 = new ImageIcon("image/Mouse.png");
                images.setIcon(icons[0]);   
                System.out.println("picture 4 should be displayed here");  
            }
            if(i == 5)
            {
                timer.stop();
                System.exit(0);
            }
            revalidate();
            repaint();
        }
    };

    public SlideShow()
    {
        JFrame frame = new JFrame("SLIDE SHOW");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);

        frame.getContentPane().add(this);

        add(images);

        frame.setSize(300, 300);
        frame.setVisible(true); 
        timer = new Timer(2000, action);    
        timer.start();  
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new SlideShow();
            }
        });
    }
}

Since you doing it with ImageIO, here is a good example related to that JLabel using ImageIO

Information relating to your case, as to what is happening :

Inside your createAndShowGUI() method you initializing your JLabel (swingImage), and you added that to your JPanel by virtue of which indirectly to the JFrame.

But now inside your updateImage() method, you are initializing a new JLabel, now it resides in some another memory location, by writing tempImage = new JLabel(new ImageIcon(scaledImage)); and after this you pointing your swingImage(JLabel) to point to this newly created JLabel, but this newly created JLabel was never added to the JPanel, at any point. Hence it will not be visible, even if you try revalidate()/repaint()/setVisible(...). Hence either you change the code for your updateImage(...) method to this :

protected void updateImage(String name) 
{
    BufferedImage image = null;
    Image scaledImage = null;
    JLabel tempImage;

    try
    {
        image = ImageIO.read(new File(name));
    } 
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    // getScaledImage returns an Image that's been resized 
    // proportionally to my thumbnail constraints
    scaledImage = getScaledImage(image, THUMB_SIZE_X, THUMB_SIZE_Y);
    tempImage = new JLabel(new ImageIcon(scaledImage));
    rightPane.remove(swingImage);
    swingImage = tempImage;
    rightPane.add(swingImage, BorderLayout.PAGE_START);
    rightPane.revalidate();
    rightPane.repaint(); // required sometimes
}

Or else use JLabel.setIcon(...) as mentioned earlier 🙂

UPDATED THE ANSWER

Here see how a New JLabel is placed at the position of the old one,

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

public class SlideShow extends JPanel
{
    private int i = 0;
    private Timer timer;
    private JLabel images = new JLabel();
    private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"),
                            UIManager.getIcon("OptionPane.errorIcon"),
                            UIManager.getIcon("OptionPane.warningIcon")};
    private ActionListener action = new ActionListener()
    {
        public void actionPerformed(ActionEvent ae)
        {                       
            i++;
            System.out.println(i);          

            if(i == 4)
            {
                timer.stop();
                System.exit(0);
            }
            remove(images);
            JLabel temp = new JLabel(icons[i - 1]);
            images = temp;
            add(images);
            revalidate();
            repaint();
        }
    };

    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("SLIDE SHOW");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);    

        this.setLayout(new FlowLayout(FlowLayout.LEFT));    

        add(images);

        frame.getContentPane().add(this, BorderLayout.CENTER);

        frame.setSize(300, 300);
        frame.setVisible(true); 
        timer = new Timer(2000, action);    
        timer.start();  
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new SlideShow().createAndDisplayGUI();
            }
        });
    }
}

And for your Question : Of the two options that I have tried, is one better than the other?

setIcon(...) has an edge over the other way, in the sense, you doesn’t have to bother about revalidate()/repaint() thingy after adding/remove JLabel. Moreover, you don’t need to remember the placement of your JLabel everytime, you add it. It remains at it’s position, and you simply call the one method to change the image, with no strings attached and the work is done, without any headaches.

And for Question 2 : I had a bit of doubt, as to what is Array of Records ?

Leave a Comment