Image Preview in JFileChooser

I just put together a little code to show an image preview in the JFileChooser. It shows a scaled image on the right side of the file chooser. The image is scaled to completely fit inside the box to the right.

ImageFileChooser
The file chooser does not filter files. It allows the user to select any file but if it can be opened as an image, the preview is shown.
I created a component based on JPanel for the preview which overrides the paintComponent method:

package x.y.z.util;

import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;

public class ImagePanel extends JPanel
{

    private Image image;
    private Image scaledCache;

    public ImagePanel()
    {
        setBorder(javax.swing.BorderFactory.createEtchedBorder());
    }

    public void setImage (Image image)
    {
        this.image = image;
        scaledCache = null;
        repaint();
    }

    private Image getScaled()
    {
        int iw = image.getWidth(this);
        int ih = image.getHeight(this);
        int pw = getWidth();
        int ph = getHeight();
        double scale;
        if (1.0 * pw / iw < 1.0 * ph / ih)
        {
            scale = 1.0 * pw / iw;
        }
        else
        {
            scale = 1.0 * ph / ih;
        }
        int scaledw = (int) (iw * scale);
        int scaledh = (int) (ih * scale);
        if (scaledCache != null)
        {
            if (scaledCache.getWidth(this) == scaledw &&
                    scaledCache.getHeight(this) == scaledh)
            {
                return scaledCache;
            }
        }
        scaledCache = image.getScaledInstance(scaledw, scaledh, Image.SCALE_DEFAULT);
        return scaledCache;
    }

    @Override
    public void paintComponent(Graphics g)
    {
        if (g != null)
        {
            Graphics scratch = g.create();
            scratch.setColor(getBackground());
            scratch.fillRect(0, 0, getWidth(), getHeight());
            if (image != null)
            {
                Image scaled = getScaled();
                scratch.drawImage(scaled, getWidth() / 2 - scaled.getWidth(this) / 2,
                        getHeight() / 2 - scaled.getHeight(this) / 2, this);
            }
        }
    }
}

Then I created a the class ImageFileChooser derived from JFileChooser:

package x.y.z.util;

import java.awt.Dimension;
import java.awt.Image;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;

public class ImageFileChooser extends JFileChooser {

    public ImageFileChooser()
    {
        final ImagePanel preview = new ImagePanel();
        preview.setPreferredSize(new Dimension (150, 150));
        setAccessory(preview);
        addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent e)
            {
                String propertyName = e.getPropertyName();
                if (propertyName.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY))
                {
                    File selection = (File) e.getNewValue();
                    String name;
                    if (selection == null)
                    {
                        return;
                    }
                    else
                    {
                        name = selection.getAbsolutePath();
                    }
                    ImageIcon icon = new ImageIcon(name);
                    Image newImage = icon.getImage();
                    preview.setImage (newImage);
                }
            }
        });
    }
}

Works great.

Leave a Reply

Your email address will not be published. Required fields are marked *