简体   繁体   English

来自构造函数的repaint()调用

[英]repaint() call from the constructor

I'm trying to display loaded resource-image. 我正在尝试显示加载的资源图像。 And it works, but only after user resized the 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();
    } 
}

Why the constructor's repaint() call doesn't work? 为什么构造函数的repaint()调用不起作用? And what should I do to show this image from the start? 从头开始我应该怎么做才能显示此图像?

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

Okay, so a bunch of things... 好吧,一堆东西...

First... 第一...

Because the window has not yet been realised on the screen (attached to a native peer), there is nothing for repaint to paint... 由于尚未在屏幕上实现该窗口(附加到本机同级窗口),因此无需repaint即可...

Second... 第二...

Toolkit.getDefaultToolkit().getImage(rl.getClass().getResource("images/" + fileName));

Passes the actually loading of the image to a background thread, meaning that while you get a non-null value returned, the actual image data might not have been fully loaded. 将图像的实际加载传递到后台线程,这意味着尽管返回了非null值,但实际图像数据可能尚未完全加载。

You should consider using ImageIO.read instead, it will only return AFTER the image data has been fully loaded and will also throw an exception if something goes wrong (unlike Toolkit.getImage ). 您应该考虑使用ImageIO.read ,它只会在图像数据已完全加载后返回,并且如果出现问题也将引发异常(与Toolkit.getImage不同)。 See Reading/Loading an Image for more details... 有关更多详细信息,请参见读取/加载图像

Third... 第三...

All Swing components implement the ImageObserver interface, this means when you call Graphics#drawImage , you should pass the object as the ImageObserver parameter 所有Swing组件都实现ImageObserver接口,这意味着在调用Graphics#drawImage ,应将对象作为ImageObserver参数传递

g.drawImage(img, 0,0, this);

This allows the component to monitor updates from the loading of the image and reschedule repaint as required. 这使组件可以监视图像加载的更新,并根据需要重新计划重绘。

Fourth... 第四...

You should avoid overriding paint of top level containers, apart from not been double buffered, there is a bunch of components between the frame and the user, which can interfere with the painting process. 您应该避免覆盖顶级容器的paint ,除了没有被双重缓冲之外,在框架和用户之间还有很多组件,这可能会干扰绘画过程。

Instead, you should extend from something like JPanel and override it's paintComponent method, performing your custom painting there. 相反,您应该从类似JPanel扩展并覆盖它的paintComponent方法,并在那里执行自定义绘制。 You should then add this panel to an instance of JFrame (or some other component as needed) 然后,您应该将此面板添加到JFrame的实例(或根据需要的其他组件)中

Take a look at Painting in AWT and Swing and Performing Custom Painting for more details 看看AWT中的绘画和摇摆执行自定义绘画以了解更多详细信息

Fifth... 第五...

You should be making sure that you create and modify your UI only from within the context of the Event Dispatching Thread, see Initial Threads for more details 您应该确保仅在事件调度线程的上下文中创建和修改UI,有关更多详细信息,请参见初始线程

Paint is immediately called when the code is initialized. 初始化代码后立即调用Paint。 To see this, get rid of repaint(); 要看到这一点,摆脱repaint(); in your constructor, and add in your paint method, g.drawLine(0, 0, 300, 300) ; 在您的构造函数中,并添加paint方法g.drawLine(0, 0, 300, 300) ;

Try this, you may have to add some imports: 尝试此操作,您可能必须添加一些导入:

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

Resource Loader: 资源加载器:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM