Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么JFrame的背景图像只有在我在Swing中调整窗口大小后才会显示?_Java_Image_Swing_Resize - Fatal编程技术网

Java 为什么JFrame的背景图像只有在我在Swing中调整窗口大小后才会显示?

Java 为什么JFrame的背景图像只有在我在Swing中调整窗口大小后才会显示?,java,image,swing,resize,Java,Image,Swing,Resize,我注意到一些奇怪的行为,设置一个图像作为我的JFrames的背景。我希望在创建两个帧时都显示背景图像。 当我在主方法中创建Window1时,它仅在我手动调整窗口大小后显示背景。单击Window1中的按钮并在Window1中创建window2时,window2会正确显示背景图像。当我在主方法中创建Window2时,背景图像也不能正确显示 import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; impor

我注意到一些奇怪的行为,设置一个图像作为我的JFrames的背景。我希望在创建两个帧时都显示背景图像。 当我在主方法中创建Window1时,它仅在我手动调整窗口大小后显示背景。单击Window1中的按钮并在Window1中创建window2时,window2会正确显示背景图像。当我在主方法中创建Window2时,背景图像也不能正确显示

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TestStart {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Window1();
            }
        });
    }
}

public class Window1 extends JFrame {

    Image img = Toolkit.getDefaultToolkit().getImage("C:\\Users\\Tim\\Desktop\\water.jpg");

    public Window1() {
        super("gridtest");

        setSize(600, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        this.setContentPane(new JPanel(){
            public void paintComponent(Graphics g){
                super.paintComponent(g);
                g.drawImage(img,0,0,getWidth(),getHeight(),null);
            }
        });

        JButton btn = new JButton("klick");
        add(btn, BorderLayout.CENTER);

        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                new Window2();
            }
        });
        pack();
        setVisible(true);
    }
}

public class Window2 extends JFrame {

    Image img = Toolkit.getDefaultToolkit().getImage("C:\\Users\\Tim\\Desktop\\water.jpg");

    public Window2() {
        super("gridsecond");

        setSize(600, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        this.setContentPane(new JPanel(){
            public void paintComponent(Graphics g){
                super.paintComponent(g);
                g.drawImage(img,0,0,getWidth(),getHeight(),null);
            }
        });
        pack();
        setVisible(true);
    }
}
我尝试添加revalidate()/repaint()调用,并在代码中的不同点调用paint方法,但除了上面描述的奇怪行为外,我无法在不调整窗口大小的情况下显示背景图像


免责声明:我知道为每个窗口创建一个新的JFrame不是一个好的做法,但我无法更改整个项目结构,因此我坚持这样做。

因此,一系列问题可能会导致您的问题

首先,使用
Toolkit.getDefaultToolkit().getImage

Image img = Toolkit.getDefaultToolkit().getImage("C:\\Users\\Tim\\Desktop\\water.jpg");
问题是,图像加载在一个单独的线程上。这意味着当
getImage
返回时,图像可能已加载,也可能尚未加载

其次,在调用
drawImage
时,您将
null
作为
ImageConsumer
传递,因此组件不会收到图像“已加载”状态更改的通知,也无法相应地安排组件的更新

this.setContentPane(new JPanel(){
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(img,0,0,getWidth(),getHeight(),null);
    }
});
第三,这更多的是一个副作用,但是,您已经使用
JPanel
手动设置
contentPane
,默认情况下使用
FlowLayout
,因此使用
BorderLayout
约束实际上是毫无意义的

setLayout(new BorderLayout());

this.setContentPane(new JPanel(){
//...
JButton btn = new JButton("klick");
add(btn, BorderLayout.CENTER);
此外,
BorderLayout
是基于窗口的组件使用的默认布局管理器;)

那么,您将如何解决此问题?那么,您可以立即将
作为
图像消费者
传递

g.drawImage(img,0,0,getWidth(),getHeight(),this);
这将允许组件监视映像的加载状态,并根据需要触发重新绘制

一个长期的解决方案是停止使用
Toolkit.getDefaultToolkit().getImage
(扩展为
ImageIcon
),因为它们可能会让人讨厌,而开始使用
ImageIO


除了支持更广泛的图像格式外,API在图像完全加载或出现错误之前不会返回(请尝试诊断其他API的加载问题,我已更改为ImageIO以读取图像,现在它可以按预期工作,谢谢!阅读您非常专业的答案总是一件非常高兴的事!+1