Java - 更改 JLabel 的图标不起作用

标签 java swing jframe jlabel embedded-resource

我正在尝试更改 JLabel 的图标(背景),但遇到图标未更新的问题。每当我尝试 lblStatusImg.setIcon(new ImageIcon(Brix_Updater_Module.class.getResource("/resources/fail.png"))); 更改 main 方法中的 JLabel 时,编译器首先会提示变量 lblStatusImg 不存在,因此我将其从 JFrame 初始化方法移至类级别变量。此后,Eclipse 提示我试图从静态上下文引用非静态方法,因此我将 lblStatusImg 设为静态。这使得程序可以编译,但图标并没有在它应该改变的时候改变。

因为有点难以理解我的问题here is a download link for an Eclipse workspace这说明了我的问题。当您第一次打开它时,您会发现它存在一些问题。它们是故意留在那里的,是为了让你更容易看到我在哪里遇到困难。如果 Eclipse 要求您将相关项目设为静态,只需执行此操作,然后运行程序即可。您会注意到它并没有按应有的方式更改标签图标。

由于并非所有人都拥有 Eclipse,因此这里是工作区中的完整代码。

import java.awt.Component;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;

import java.awt.Font;

import javax.swing.SwingConstants;

import java.awt.Window.Type;
import java.io.BufferedOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Timer;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import javax.swing.JButton;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;


public class StackOverflow_Image_Resource_Demo {

    private JFrame frmUpdate;
    JLabel lblStatusImg = new JLabel("");
    JButton btnUpdateComplete = new JButton("OK");

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    StackOverflow_Image_Resource_Demo window = new StackOverflow_Image_Resource_Demo();
                    window.frmUpdate.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        try {
            lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("success.png")));
            btnUpdateComplete.setVisible(true);
        }
        catch(Exception e)
        {
            Component frame = null;
            lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("/resources/fail.png")));
            JOptionPane.showMessageDialog(frame, "Update Failed", "Update Failed", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        }
    }

    /**
     * Create the application.
     */
    public StackOverflow_Image_Resource_Demo() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frmUpdate = new JFrame();
        frmUpdate.setType(Type.UTILITY);
        frmUpdate.setTitle("StackOverflow Image Resource Issue Demo");
        frmUpdate.setBounds(100, 100, 450, 300);
        frmUpdate.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmUpdate.getContentPane().setLayout(null);

        //JLabel lblStatusImg = new JLabel(""); - Commented out when I made lblStatusImg class level.
        lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("/resources/updating.gif")));
        lblStatusImg.setBounds(10, 22, 414, 97);
        frmUpdate.getContentPane().add(lblStatusImg);

        //JButton btnUpdateComplete = new JButton("OK"); - Commented out when I made btnUpdateComplete class level.
        btnUpdateComplete.setVisible(false);
        btnUpdateComplete.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent arg0) {
                System.exit(1);
            }
        });
        btnUpdateComplete.setBounds(170, 179, 89, 23);
        frmUpdate.getContentPane().add(btnUpdateComplete);
    }
}

这是我的代码的较新版本,用于更新图像,但在完成其他所有操作之前不会完全加载 UI。

import java.awt.Component;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;

import java.awt.Font;

import javax.swing.SwingConstants;

import java.awt.Window.Type;
import java.io.BufferedOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Timer;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import javax.swing.JButton;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;


public class StackOverflow_Image_Resource_Demo {

    private JFrame frmUpdate;
    JLabel lblStatusImg = new JLabel("");
    JButton btnUpdateComplete = new JButton("OK");

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    StackOverflow_Image_Resource_Demo window = new StackOverflow_Image_Resource_Demo();

尝试{ lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("success.png"))); btnUpdateComplete.setVisible(true); } 捕获(异常 e) { 组件框架 = null; lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("/resources/fail.png"))); JOptionPane.showMessageDialog(frame, "更新失败", "更新失败", JOptionPane.ERROR_MESSAGE); 系统.退出(1); } window.frmUpdate.setVisible(true); } catch (异常 e) { e.printStackTrace(); } } }); }

    /**
     * Create the application.
     */
    public StackOverflow_Image_Resource_Demo() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frmUpdate = new JFrame();
        frmUpdate.setType(Type.UTILITY);
        frmUpdate.setTitle("StackOverflow Image Resource Issue Demo");
        frmUpdate.setBounds(100, 100, 450, 300);
        frmUpdate.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmUpdate.getContentPane().setLayout(null);

        //JLabel lblStatusImg = new JLabel(""); - Commented out when I made lblStatusImg class level.
        lblStatusImg.setIcon(new ImageIcon(StackOverflow_Image_Resource_Demo.class.getResource("/resources/updating.gif")));
        lblStatusImg.setBounds(10, 22, 414, 97);
        frmUpdate.getContentPane().add(lblStatusImg);

        //JButton btnUpdateComplete = new JButton("OK"); - Commented out when I made btnUpdateComplete class level.
        btnUpdateComplete.setVisible(false);
        btnUpdateComplete.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent arg0) {
                System.exit(1);
            }
        });
        btnUpdateComplete.setBounds(170, 179, 89, 23);
        frmUpdate.getContentPane().add(btnUpdateComplete);
    }
}

最佳答案

有两件事被发现。第一个是,正如您所说,您试图从静态上下文引用非静态变量。

第二是,你似乎不明白线程是如何工作的......

基本上,main通常在“主”线程中执行(当由 JVM 执行时)。

然后您使用 EventQueue.invokeLater 。顾名思义,它将执行 Runnable “稍后”...将来的某个时候...

        EventQueue.invokeLater(new Runnable() {
            public void run() {

然后,您尝试更改图标(让我们暂时忽略非静态引用)...但是 lblStatusImg不会被初始化,也不会被显示,如 Runnable尚未执行,这意味着,即使您没有遇到 NullPointerException ,您将看不到更改...

您可以通过添加 System.out 进行测试在你的Runnable在第一个 lblStatusImg.setIcon 之前调用main方法。

你应该做的是......

  1. 将“状态”更改移至 Runnable 内上下文。
  2. 提供 setStatus能够根据提供状态根据需要更改标签和 UI 内容的方法

例如...

public static final int SUCCESS = 0;
public static final int FAIL = 0;

//...

public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    StackOverflow_Image_Resource_Demo window = new StackOverflow_Image_Resource_Demo();
                    // This e
                    window.frmUpdate.setVisible(true);

                    window.setStatus(StackOverflow_Image_Resource_Demo.SUCCESS);
                } catch (Exception e) {
                    e.printStackTrace();
                    Component frame = null;
                    window.setStatus(StackOverflow_Image_Resource_Demo.FAIL);
                    JOptionPane.showMessageDialog(frame, "Update Failed", "Update Failed", JOptionPane.ERROR_MESSAGE);
                    window.dispose();
                }
            }
        });
    }

您应该避免将实例字段公开为 public相反,提供间接更改其状态的方法(例如 setStatus )或直接更改其状态( setStatusIcon )。在这种情况下,我更喜欢第一种方法,因为这允许类确定状态更改的实际含义。

关于Java - 更改 JLabel 的图标不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22598274/

相关文章:

java - 使用 Nimbus LaF 设置 JMenuItems 边框

java - 另一个 JFrame 中的 JFrame

java - 如何将新元素添加到 JFrame 并显示它

java - 找不到包或没有 package-info.java

java - “JavaPackage”对象不可调用

java - 我什么时候应该使用基元而不是包装对象?

java - 如何使边框适合 JLabel

java - 使用 Apache-POI 获取 docx 的每个段落的行

Java Swing JScrollPane 按住 Shift 并使用鼠标滚轮时不滚动

java - 从另一个类 JFrame 调用重绘