Monthly Archives: September 2009

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.

Netbeans Debugger Problems

My colleague Chris Andritzky keeps getting bitten by problems of the Netbeans Debugger. In a multi threaded application, threads are stopped by breakpoints but the debugger does not realize it.
It seems there are two bugs behind this, one in JDK6 and one in the Netbeans Debugger.
The bug is described in Issue 167776. The JDK6 bug is supposedly fixed in Update 16. The Netbeans bug will be fixed in Netbeans 6.8. Chris is going to try Netbeans 6.8 Milestone 1.

Update:
Chris tried updating to Update 16 first. This didn’t help. Updating to Netbeans 6.8 Milestone 1 solved the problem though.