【问题标题】:JButton setIcon Updation errorJButton setIcon 更新错误
【发布时间】:2012-06-19 15:13:06
【问题描述】:

目前我正在使用基于更改按钮图像的netbeans制作一个java程序....

实际上我的要求是在我单击另一个按钮时更改按钮的图像图标(说 A).....

我提出了以下程序........

       // 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);

         }

我包含的变量是

           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....

现在我观察到的奇怪行为是......

仅当我单击最小化按钮时,图像才会在按钮单击时显示。 即当我单击按钮 A 时,ActionListener 中指定的代码将被执行。但是只有当我最小化窗口并再次使其出现在屏幕上时,图像更改的效果才会出现.... 谁能说出为什么会发生这种情况以及如何解决问题?

我只想在单击 A 按钮的那一刻更改图像..... 嗯..我没有包含用于创建按钮的代码,因为它们很容易由 netbeans swing GUI builder 完成......

【问题讨论】:

标签: java swing netbeans jbutton imageicon


【解决方案1】:
  1. Icon/ImageIcon加载为局部变量一次,没有理由从ActionListener重新加载图像

  2. API 中描述Image#ScaledInstance 是相当异步的

  3. 否则你必须打电话

.

labelicon.getImage().flush();
img_btn.setIcon(labelicon);

编辑

@akp 写道,但是..你将如何调整图标图像的大小..??

有两种或三种其他方式可以放置 Icon /ImageIcon 并且可以通过其父级调整大小,JLabel 可能是最简单的方式

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;
    }
}

【讨论】:

  • 但是..你将如何调整图标图像的大小..??
【解决方案2】:

这里的问题是您正在更新Icon 的内部结构。 setIcon 方法会认为它与按钮已有的图标相同。我建议您使用 两个不同的 Icon 对象 来更新图标。这将解决问题。


示例(带有两个不同的图标):

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);
}

背景:

查看AbstractButton.setIcon的来源,可以看到如果引用“未更新”,它不会知道更新:

    .....
    if (defaultIcon != oldValue) {
        if (defaultIcon == null || oldValue == null ||
            defaultIcon.getIconWidth() != oldValue.getIconWidth() ||
            defaultIcon.getIconHeight() != oldValue.getIconHeight()) {
            revalidate();
        } 
        repaint();
    }

@HarryJoy 请注意,即使您不知道为什么,您实际上也有道理... :) 抱歉!再次 +1!

【讨论】:

  • 但是......我想知道它是否改变了图标......该变化的反映应该出现在它的对象属性中......
  • 它会更改图标对象,但您需要告诉 GUI 它需要更新,这与对 setIcon 的任何其他调用不同。
  • 嗯..我有一点。欢呼!!!! \m/ :p 。但我得到了一个减分点:(任何很好的解释。:)
【解决方案3】:

//致电img_btn.revalidate()img_btn.repaint()

更正,setIcon 应该已经这样做了。我个人使用img_btn.setText("<HTML><BODY><IMG SRC=\"/path/to/img.jpg\"/></BODY</HTML>");的hacky方式。

【讨论】:

  • -1 那没有任何用处。 setIcon 已经这样做了(检查源代码)。
  • 不,伙计,setIcon 已经这样做了(正如 dacwe 所说)。我刚刚发布了相同的内容,但随后被删除,导致其错误。
  • @apk 看起来是这样,但我不记得 ./ 是什么目录了。例如。 icon.jpg 与班级在同一个文件夹中吗? /是根目录还是jar?有人知道吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
  • 2013-07-06
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多