Java 为什么JFrame的背景图像只有在我在Swing中调整窗口大小后才会显示?
我注意到一些奇怪的行为,设置一个图像作为我的JFrames的背景。我希望在创建两个帧时都显示背景图像。 当我在主方法中创建Window1时,它仅在我手动调整窗口大小后显示背景。单击Window1中的按钮并在Window1中创建window2时,window2会正确显示背景图像。当我在主方法中创建Window2时,背景图像也不能正确显示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
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