Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java ImageIcon size

Tags:

java

swing

I have uploaded a picture into my GUI which displays on a JLabel. The label dimension is set only 100,100 while the picture is much bigger, so when I upload it into the label it expands.

Is there anyway to make it auto resize to the label size?

Below is the action listener for the Upload Picture JButton

class UploadHandler implements ActionListener 
{
    public void actionPerformed(ActionEvent e)
    {
        int returnVal = fc.showOpenDialog(frame2);
        file = fc.getSelectedFile();
        pathname = file.getPath();
        icon = new ImageIcon(pathname);
        lblDisPic.setIcon(icon);    
    }
}

btnUpload = new JButton("Upload Picture");
lblDisPic = new JLabel();
lblDisPic.setBorder(raisedetched);
lblDisPic.setPreferredSize(d); 

btnUpload.addActionListener(new UploadHandler());
like image 418
sutoL Avatar asked Feb 11 '10 13:02

sutoL


3 Answers

Given the example code, one approach is to resize the image to display on the JLabel before the setIcon method is called.

One way could be to change the actionPerformed method, so the image will be loaded from the specified file, using ImageIO.read method to read the image, then resizing the image before an ImageIcon is created.

Image img = ImageIO.read(fc.getSelectedFile());

Then, the loaded image can be resized to the dimension of the JLabel, using Image.getScaledInstance.

Image resizedImage = 
    img.getScaledInstance(lblDisPic.getWidth(), lblDisPic.getHeight(), null);

Now, one could create an ImageIcon to use on the JLabel.

lblDisPic.setIcon(new ImageIcon(resizedImage));

The limitation to this method is, that if the JLabel is resized in any way, then the image contained by the JLabel will not be resized. However, as the JLabel is going to use a scaled-down image of the original, it would mean that the amount of memory required would be reduced (if that a concern) and original image would not have to be resized every time image is being displayed, as would be the case with overriding the paintComponent method.

The preferred method of achieving the task at hand is going to depend on the requirements of whether the original image is going to be needed at a later time or not.

like image 101
coobird Avatar answered Sep 20 '22 02:09

coobird


Sure, just override the paintComponent method and you can scale and paint it as you like.

myLabel = new JLabel (/*whatever*/) {

    @Override
    public void paintComponent (Graphics g) {
        super.paintComponent (g);
        g.drawImage (myImageIcon.getImage(), 0, 0, getWidth (), getHeight (), null);
    }
};

Source from here.

EDIT

To add to your code change:

lblDisPic = new JLabel();

To:

lblDidPic = new JLabel() {

    @Override
    public void paintComponent (Graphics g) {
        super.paintComponent (g);
        if (icon != null) {
            g.drawImage (icon.getImage(), 0, 0, getWidth(), getHeight(), null);
        }
    }
};
like image 39
Pool Avatar answered Sep 21 '22 02:09

Pool


You could override the paintIcon method on the icon itself -

ImageIcon icon = new ImageIcon(...) {

    @Override
    public void paintIcon( Component c, Graphics g, int x, int y ) {
        g.drawImage(getImage(), x, y, c.getWidth(), c.getHeight(), c);
    }

    @Override 
    public int getIconHeight() {
        // see below...
    }

    @Override
    public int getIconWidth() {
        // see below...
    }

};

Edit -

I realized that the original size of the image is taken into account when the Label decides where to place the x, y location of the icon. You'll need to override the getIconWidth() and getIconHeight() methods, too.

However, there's not a good way to override these to return the label size, as there's no reference to the component itself within these methods.

One approach would be to create a new class that extends ImageIcon and pass the component in - not a great choice because this breaks the "reusable between many components" aspects of an Icon.

Another would be to just override these methods in the inner class as above, but put a hardcoded reference to the component as an object field, or as a final local variable. Again, this breaks the "reusable between many components" aspect, and seems a bit "hacky" in general, but as it is an one-off inner class, this might be permissable.

like image 34
Nate Avatar answered Sep 18 '22 02:09

Nate