Reputation: 2111
Currently i m making a java program using netbeans based on changing image in a button....
Actually my requirement is to change the Image icon of a button as i click another button (Say A).....
i came out with the following program........
// Following function is included inside the button's (Here A) ActionListener........
public void change_image()
{
if(sex==0)
{
ic=new ImageIcon("E:\\java_images\\female_profile.jpg");
sex=1;
}
else if(sex==1)
{
ic = new ImageIcon("E:\\java_images\\male_profile.png");
sex=0;
}
// To resize the image into the size of the button...
labelicon.setImage(ic.getImage().getScaledInstance(image_btn.getWidth(),image_btn.getHeight(), Image.SCALE_DEFAULT));
img_btn.setIcon(labelicon);
}
The Variables i've included are
private int sex; // 0 - female, 1 - male
private ImageIcon ic,labelicon; // variables meant for storing ImageIcons.....
private JButton img_btn; // the button at which the image is to be displayed....
Now the Weird Behaviour i observed is.......
The image gets displayed on the button click, only when i click the minimize button. i.e when the i click the button A, the code specified in the ActionListener is getting executed. But the effect of the image change appears only when i minimize the window and again make it appear on the screen.... Can anyone tell why this is occuring and how can i remove the problem ??
All i want is to change the image the moment i click the A Button..... Well..i haven't included for the code for creating button since they are easily done by netbeans swing GUI builder......
Upvotes: 0
Views: 1963
Reputation: 109813
load Icon
/ ImageIcon
as local variable once time, there no reason to re_loading image from ActionListener
in the API is description that Image#ScaledInstance
is pretty asynchronous
otherwise you have to call
.
labelicon.getImage().flush();
img_btn.setIcon(labelicon);
EDIT
@akp wrote but..how would you resize the icon image..??
there are two or three another ways how to put Icon /ImageIcon and will be resiziable with its parent, JLabelcould be easiest of ways
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.swing.*;
public class JButtonAndIcon {
private static JLabel label = new JLabel();
private static Random random = new Random();
private static ImageIcon image1; // returns null don't worry about
private static ImageIcon image2; // returns null don't worry about
private static Timer backTtimer;
private static int HEIGHT = 300, WEIGHT = 200;
public static void main(String[] args) throws IOException {
label.setPreferredSize(new Dimension(HEIGHT, WEIGHT));
final JButton button = new JButton("Push");
button.setBorderPainted(false);
button.setBorder(null);
button.setFocusable(false);
button.setMargin(new Insets(0, 0, 0, 0));
button.setContentAreaFilled(false);
button.setLayout(new BorderLayout());
button.add(label);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (button.getIcon() == image1) {
label.setIcon(image2);
} else {
label.setIcon(image1);
}
}
});
JFrame frame = new JFrame("Test");
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
startBackground();
frame.setVisible(true);
}
private static void startBackground() {
backTtimer = new javax.swing.Timer(750, updateBackground());
backTtimer.start();
backTtimer.setRepeats(true);
}
private static Action updateBackground() {
return new AbstractAction("Background action") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
label.setIcon(new ImageIcon(getImage()));
}
};
}
public static BufferedImage getImage() {
int w = label.getWidth();
int h = label.getHeight();
GradientPaint gp = new GradientPaint(0f, 0f, new Color(
127 + random.nextInt(128),
127 + random.nextInt(128),
127 + random.nextInt(128)),
w, w,
new Color(random.nextInt(128), random.nextInt(128), random.nextInt(128)));
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
g2d.setColor(Color.BLACK);
return bi;
}
}
Upvotes: 3
Reputation: 43504
The problem here is that you are updating the internals of an Icon
. The setIcon
method will think that it's the same icon that the button already has. I would recommend you to do two different Icon
objects that to use to update the icon with. That will fix the problems.
public static void main(String[] args) throws IOException {
final ImageIcon redIcon = createImageIcon(10, 10, Color.RED);
final ImageIcon blueIcon = createImageIcon(10, 10, Color.BLUE);
final JButton button = new JButton("Push", blueIcon);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (button.getIcon() == redIcon)
button.setIcon(blueIcon);
else
button.setIcon(redIcon);
}
});
JFrame frame = new JFrame("Test");
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static ImageIcon createImageIcon(int w, int h, Color color) {
Image image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
g.setColor(color);
g.fillRect(0, 0, w, h);
g.dispose();
return new ImageIcon(image);
}
Looking at the source of AbstractButton.setIcon
, you can see that it won't know about the update if the reference "isn't updated":
.....
if (defaultIcon != oldValue) {
if (defaultIcon == null || oldValue == null ||
defaultIcon.getIconWidth() != oldValue.getIconWidth() ||
defaultIcon.getIconHeight() != oldValue.getIconHeight()) {
revalidate();
}
repaint();
}
Note to @HarryJoy, you actually had a point even though you didn't know why... :) Sorry! +1 again!
Upvotes: 2
Reputation: 282
//Call img_btn.revalidate()
and img_btn.repaint()
Correction, setIcon should already do this. I use the hacky way of img_btn.setText("<HTML><BODY><IMG SRC=\"/path/to/img.jpg\"/></BODY</HTML>");
personally.
Upvotes: 1