我正在尝试更改 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
方法。
你应该做的是......
- 将“状态”更改移至
Runnable
内上下文。 - 提供
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/