5

Whenever I set an icon for my JButton it is always not sized correctly. How can I resize the icon to fit the button fully?

final JButton btnSanic = new JButton();
Image img = icon.getImage();
Image newimg = img.getScaledInstance(width, height, java.awt.Image.SCALE_SMOOTH);
icon = new ImageIcon(newimg);  
btnSanic.setIcon(icon);
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
Arman
  • 655
  • 2
  • 7
  • 23
  • Show us how you do it now and what exactly is incorrect about it. – PM 77-1 Sep 11 '14 at 22:49
  • I tried this: Image img = icon.getImage(); Image newimg = img.getScaledInstance(width, height, java.awt.Image.SCALE_SMOOTH); icon = new ImageIcon(newimg); but I don't really know what to replace the "icon" in "Image img = icon.getImage();" – Arman Sep 11 '14 at 22:51
  • Paste the content of your comment into your post (click on `edit`) and format it. – PM 77-1 Sep 11 '14 at 22:54
  • Done, sorry about that – Arman Sep 11 '14 at 22:56
  • So what are `width` and `height` values? What are the button dimensions? – Jim Garrison Sep 11 '14 at 23:05
  • width and height are assigned to the buttons dimensions (90 x 60) – Arman Sep 11 '14 at 23:06
  • Since my answer below was deleted 9 years after it was first posted I thought I would add a comment for those who might be interested in an alternative solution. You can use the [Stretch Icon](http://tips4java.wordpress.com/2012/03/31/stretch-icon/). Just add the Icon to your component and scaling will happen automatically. – camickr Mar 09 '23 at 21:23

3 Answers3

17

There are any number of issues. To start with, all Swing components DON'T auto scale images. Sure, might be a nice idea, but given the amount of time and processing required to do it efficiently, I understand why they don't, so you need to do all the work...

You should also remember, that the size of a component is not determined until it is laid out. And while you can provide all the sizing hints you might like, the layout manager is well within its rights to ignore one or more of these hints.

Instead of "hoping" you know the size of the button, you should make use of the ComponentListener API to receive notifications of when the component is actually resized...

Auto resizable icon

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestButton {

    public static void main(String[] args) {
        new TestButton();
    }
    
    private BufferedImage master;
    
    public TestButton() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }
                
                try {
                    master = ImageIO.read(new File("C:\\svg\\Revert 256x256.png"));
                    
                    JButton btn = new JButton() {
                        
                        @Override
                        public Dimension getPreferredSize() {
                            return new Dimension(90, 50);
                        }
                        
                    };
                    btn.addComponentListener(new ComponentAdapter() {
                        
                        @Override
                        public void componentResized(ComponentEvent e) {
                            JButton btn = (JButton) e.getComponent();
                            Dimension size = btn.getSize();
                            Insets insets = btn.getInsets();
                            size.width -= insets.left + insets.right;
                            size.height -= insets.top + insets.bottom;
                            if (size.width > size.height) {
                                size.width = -1;
                            } else {
                                size.height = -1;
                            }
                            Image scaled = master.getScaledInstance(size.width, size.height, java.awt.Image.SCALE_SMOOTH);
                            btn.setIcon(new ImageIcon(scaled));
                        }
                        
                    });
                    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(btn);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }
    
}

Note: This example is far from optimised, but simply provides a broad concept of a possible solution...

Now, a word of warning. Image#getScaledInstance is neither the fastest or greatest of scaling algorithms...

Take a look at...

for more details...

bobndrew
  • 395
  • 10
  • 32
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

In this code an image is resized to have the same dimensions of the JButton's object that will contain it:

JButton button = new JButton();
button.setBounds(x, y, width, height);
try{
    Image image = ImageIO.read(new File("icons/myImage.png")).getScaledInstance(width, height, Image.SCALE_DEFAULT);
    button.setIcon(new ImageIcon(image));
} 
catch (Exception e) {
}
-1

You can try change the file extension (like "jpg, png, icon") to "gif". It worked for me in Eclipse

Hai Quan Le
  • 396
  • 6
  • 11