从构造函数调用 repaint()
repaint() call from the constructor
我正在尝试显示加载的资源图像。
它有效,但只有在用户调整 window.
的大小之后
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() 调用不起作用?
我应该怎么做才能从一开始就显示这张图片?
资源加载器class:
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));
}
}
好吧,一堆东西...
首先...
因为window还没有在屏幕上实现(附加到native peer),所以repaint
没有东西可以画...
第二...
Toolkit.getDefaultToolkit().getImage(rl.getClass().getResource("images/" + fileName));
将图像的实际加载传递给后台线程,这意味着当您获得非空值时 returned,实际图像数据可能尚未完全加载。
您应该考虑使用 ImageIO.read
,它只会在图像数据完全加载后 return,并且如果出现问题也会抛出异常(与 Toolkit.getImage
不同) .有关详细信息,请参阅 Reading/Loading an Image...
第三...
所有 Swing 组件都实现了 ImageObserver
接口,这意味着当您调用 Graphics#drawImage
时,您应该将对象作为 ImageObserver
参数传递
g.drawImage(img, 0,0, this);
这允许组件监视图像加载的更新并根据需要重新安排重绘。
第四...
你应该避免覆盖paint
顶层容器,除了没有双缓冲,框架和用户之间有一堆组件,这会干扰绘画过程。
相反,您应该从 JPanel
之类的东西扩展并覆盖它的 paintComponent
方法,在那里执行您的自定义绘画。然后,您应该将此面板添加到 JFrame
的实例(或根据需要添加到其他组件)
查看 Painting in AWT and Swing and Performing Custom Painting 了解更多详情
第五...
您应该确保仅在事件调度线程的上下文中创建和修改 UI,有关详细信息,请参阅 Initial Threads
初始化代码时立即调用Paint。要看到这一点,请在构造函数中删除 repaint();
,并在 paint
方法中添加 g.drawLine(0, 0, 300, 300)
;
试试这个,您可能需要添加一些导入:
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");
setVisible(true);
}
@Override
public void paint (Graphics g){
super.paint(g);
if (img != null)
g.drawImage(img, 0,0, this);
}
}
public class ResourcesProgram {
public static void main(String[] args) {
new MyMainWindow();
}
}
资源加载器:
import javax.swing.*; import java.awt.*;
public class MyResourceLoader {
public static Image getImage(String fileName){
ImageIcon icon = new ImageIcon(getClass().getResource(fileName));
return icon.getImage();
}
}
我正在尝试显示加载的资源图像。 它有效,但只有在用户调整 window.
的大小之后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() 调用不起作用? 我应该怎么做才能从一开始就显示这张图片?
资源加载器class:
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));
}
}
好吧,一堆东西...
首先...
因为window还没有在屏幕上实现(附加到native peer),所以repaint
没有东西可以画...
第二...
Toolkit.getDefaultToolkit().getImage(rl.getClass().getResource("images/" + fileName));
将图像的实际加载传递给后台线程,这意味着当您获得非空值时 returned,实际图像数据可能尚未完全加载。
您应该考虑使用 ImageIO.read
,它只会在图像数据完全加载后 return,并且如果出现问题也会抛出异常(与 Toolkit.getImage
不同) .有关详细信息,请参阅 Reading/Loading an Image...
第三...
所有 Swing 组件都实现了 ImageObserver
接口,这意味着当您调用 Graphics#drawImage
时,您应该将对象作为 ImageObserver
参数传递
g.drawImage(img, 0,0, this);
这允许组件监视图像加载的更新并根据需要重新安排重绘。
第四...
你应该避免覆盖paint
顶层容器,除了没有双缓冲,框架和用户之间有一堆组件,这会干扰绘画过程。
相反,您应该从 JPanel
之类的东西扩展并覆盖它的 paintComponent
方法,在那里执行您的自定义绘画。然后,您应该将此面板添加到 JFrame
的实例(或根据需要添加到其他组件)
查看 Painting in AWT and Swing and Performing Custom Painting 了解更多详情
第五...
您应该确保仅在事件调度线程的上下文中创建和修改 UI,有关详细信息,请参阅 Initial Threads
初始化代码时立即调用Paint。要看到这一点,请在构造函数中删除 repaint();
,并在 paint
方法中添加 g.drawLine(0, 0, 300, 300)
;
试试这个,您可能需要添加一些导入:
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");
setVisible(true);
}
@Override
public void paint (Graphics g){
super.paint(g);
if (img != null)
g.drawImage(img, 0,0, this);
}
}
public class ResourcesProgram {
public static void main(String[] args) {
new MyMainWindow();
}
}
资源加载器:
import javax.swing.*; import java.awt.*;
public class MyResourceLoader {
public static Image getImage(String fileName){
ImageIcon icon = new ImageIcon(getClass().getResource(fileName));
return icon.getImage();
}
}