我正在尝试显示加载的资源图像。 它有效,但只有在用户调整窗口大小时。
import javax.swing.*; import java.awt.*;
class MyMainWindow extends JFrame{
Image img;
public MyMainWindow(){
setSize(300,300);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
img = MyResourceLoader.getImage("res.jpg");
repaint();
setVisible(true);
}
@Override
public void paint (Graphics g){
super.paint(g);
if (img != null)
g.drawImage(img, 0,0, null);
}
}
public class ResourcesProgram {
public static void main(String[] args) {
new MyMainWindow();
}
}
为什么构造函数的 repaint() 调用不起作用? 我应该怎么做才能从一开始就显示这张图片?
资源加载器类:
import java.awt.*;
public class MyResourceLoader{
static MyResourceLoader rl = new MyResourceLoader();
static public Image getImage(String fileName){
return Toolkit.getDefaultToolkit().getImage(rl.getClass().getResource("images/" + fileName));
}
}
最佳答案
好吧,那么一堆东西......
首先...
因为窗口还没有在屏幕上实现(附加到本地对等点),所以repaint
没有什么可以绘制的...
第二...
Toolkit.getDefaultToolkit().getImage(rl.getClass().getResource("images/" + fileName));
将图像的实际加载传递给后台线程,这意味着当您返回一个非空值时,实际图像数据可能尚未完全加载。
您应该考虑使用 ImageIO.read
,它只会在图像数据完全加载后返回,并且如果出现问题也会抛出异常(不同于 Toolkit.getImage
)。参见 Reading/Loading an Image更多详情...
第三...
所有 Swing 组件都实现了 ImageObserver
接口(interface),这意味着当您调用 Graphics#drawImage
时,您应该将对象作为 ImageObserver
参数传递
g.drawImage(img, 0,0, this);
这允许组件监 View 像加载的更新并根据需要重新安排重绘。
第四...
你应该避免重写顶级容器的paint
,除了没有双缓冲,框架和用户之间有一堆组件,这会干扰绘画过程。
相反,您应该从类似JPanel
的东西扩展并覆盖它的paintComponent
方法,在那里执行您的自定义绘画。然后,您应该将此面板添加到 JFrame
的实例(或根据需要添加到其他组件)
看看Painting in AWT and Swing和 Performing Custom Painting了解更多详情
第五...
您应该确保仅在事件调度线程的上下文中创建和修改您的 UI,请参阅 Initial Threads了解更多详情
关于java - 从构造函数调用 repaint(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28058006/