Java 如何刷新包含BuffereImage的JFrame?

Java 如何刷新包含BuffereImage的JFrame?,java,swing,jframe,bufferedimage,Java,Swing,Jframe,Bufferedimage,除了我的问题之外,我还上了以下课程来制作一个JFrame: package myprojects; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; class BackgroundImageJFrame extends JFrame { public BackgroundImageJFrame(BufferedImage img) { setTitle("Bac

除了我的问题之外,我还上了以下课程来制作一个
JFrame

package myprojects;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

class BackgroundImageJFrame extends JFrame {
    public BackgroundImageJFrame(BufferedImage img) {
        setTitle("Background Color for JFrame");
        int h = img.getHeight();
        int w = img.getWidth();
        setSize(w, h);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

        setLayout(new BorderLayout());
        setContentPane(new JLabel(new ImageIcon(img)));
        setLayout(new FlowLayout());
        // Just for refresh :) Not optional!
        setSize(w-1, h-1);
        setSize(w, h);
    }
}
我用
newbackgroundimagejframe(img)调用它。因为我想刷新这个
JFrame
的内容,所以这并不能达到最佳效果,因为每次都会创建一个新的
JFrame


我怎样才能改变它,让
JFrame
刷新?

您只需存储
JLabel
控件,然后用一种方法设置图像,就可以完成这项工作。请确保您将图像设置在屏幕上

基于@MadProgrammer的优秀评论,我修改了代码,以更稳定的方式完成这项工作

本版本与上一版本之间解决问题的简要总结:

  • 您不希望
    contentPane
    成为
    JLabel
    ,因为它使以后添加其他控件更加困难,并且没有布局管理器。我在中间添加了一个
    JPanel
    ,并给出了它
  • 调用方应负责线程安全。我最初没有这样做,因为您没有提供任何调用代码,但在这里,我执行事件分派线程委派。在调用
    setBackgroundImage()
    之前,请确保使用
    EventQueue.invokeLater
    切换到事件调度线程,就像我在main中所做的那样
  • 我正在JLabel上使用
    setSize
    setPreferredSize
    ,这样布局管理器就可以正确地为控件选择合适的大小,并按预期工作
  • 我在构造函数之外的
    initComponents
    方法中创建控件,以使代码更容易理解,并在必要时便于以后添加更多构造函数
  • 代码如下:

    public class NonogramSolutionJFrame extends JFrame {
      private final JLabel label;
      private final JPanel panel;
    
      public NonogramSolutionJFrame(BufferedImage img) {
        panel = new JPanel();
        label = new JLabel();
        initComponents(img);
      }
    
      private final void initComponents(BufferedImage img) {
        setTitle("Background Color for JFrame");
        setBackgroundImage(img);
        setContentPane(panel);
        panel.setLayout(new BorderLayout());
        panel.add(label, BorderLayout.CENTER);
        setLocationRelativeTo(null);
        pack();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
      }
    
      public void setBackgroundImage(final BufferedImage img) {
        label.setIcon(new ImageIcon(img));
        label.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
      }
    
      public static void main(String... args) throws Exception {
        BufferedImage img = ImageIO.read(NonogramSolutionJFrame.class.getResource("/nonogram.png"));
        NonogramSolutionJFrame frame = new NonogramSolutionJFrame(img);
        EventQueue.invokeLater(new Runnable() {
          @Override
          public void run() {
            frame.setVisible(true);
          }
        });
      }
    }
    
    使用来自的映像,此代码生成以下内容(在Linux上):


    请注意,使用
    JLabel
    作为“背景”图像有两个主要问题,1-默认情况下没有布局管理器,因此您需要进行设置;2-在确定标签的首选大小时,
    JLabel
    不会考虑其内容,这可能会导致问题。IMHO-确保线程安全不是
    BackgroundImageJFrame
    的责任,而是调用者的责任,否则您只是在向系统中添加可能的低效率(以及可能的竞争条件),可能会看到一个更新以您不设计的顺序发生-但这就是我;)我不反对你不修改OPs代码,但应该让他们知道他们的方法可能存在的任何缺陷,这样他们就不会陷入更深的问题,只是说;)嘿,我编辑了答案,我想让你看到它。程序员在评论中提出了一些好的观点。