Java 无法使用paintComponent设置JPanel的背景来更新其背景

Java 无法使用paintComponent设置JPanel的背景来更新其背景,java,swing,jpanel,background-image,paintcomponent,Java,Swing,Jpanel,Background Image,Paintcomponent,我正在制作一个应用程序,您可以将背景更改为任何图片,或者只保留默认图片。它由一个ImagePanel类组成,该类覆盖其paintComponent以设置一个imageicon作为其背景 我试图做的是从GUISettings类中让用户从带有过滤器的文件选择器中选择一个图像,然后将file.getPath()字符串传递到ImagePanel类并重新验证该gui,但没有更改背景,甚至没有在控制台上显示的ImagePanel中的调试打印 以下是代码(简化): ImagePanel类: public

我正在制作一个应用程序,您可以将背景更改为任何图片,或者只保留默认图片。它由一个
ImagePanel
类组成,该类覆盖其paintComponent以设置一个imageicon作为其背景

  • 我试图做的是从
    GUISettings
    类中让用户从带有过滤器的文件选择器中选择一个图像,然后将file.getPath()字符串传递到
    ImagePanel
    类并重新验证该gui,但没有更改背景,甚至没有在控制台上显示的
    ImagePanel
    中的调试打印
以下是代码(简化):

ImagePanel
类:

public class ImagePanel extends JPanel{

private String defaultbg = "Icons/background.jpg";
private String path = "";
private BufferedImage img;
private GridBagConstraints gbc = new GridBagConstraints();
public ImageIcon bgicon;
private Image bg;
public static boolean defaultbgset = true;


public ImagePanel(){

    if(defaultbgset){

        path = defaultbg;
        System.out.println("path in default = " + path);
    } else {

        if(GUISettings.getPath() != null){

            path = GUISettings.getPath();
            System.out.println("path in userBG = " + path);
        }
    }

    bgicon = new ImageIcon(getClass().getResource(path));

    bg = (new ImageIcon(bgicon.getImage().getScaledInstance(1024, 800, java.awt.Image.SCALE_SMOOTH))).getImage();
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
}

public ImageIcon getDrawBoardBackground(){

    return bgicon;
}

public void setPath(String p){

    this.path = p;
}

public void resetPath(){

    this.path = defaultbg;
}

}
public class GUISettings extends JPanel implements ActionListener{


private TitledBorder title = BorderFactory.createTitledBorder("User Interface Settings");
private JLabel lbackground, userbg;
private JTextField bgpath;
private GridBagConstraints gbc = new GridBagConstraints();
public static JRadioButton default_bg, user_bg;
private JButton browse;
public static File file;
private JLabel userfile = new JLabel("Not chosen.");

public static String userBgPath = null; 

public GUISettings(){

    //this.setLayout(new GridBagLayout());
    Dimension size = getPreferredSize();
    size.setSize(200,150); //w, h
    this.setPreferredSize(size);
    this.setBorder(title);

    JPanel toppane = new JPanel();
    toppane.setLayout(new GridBagLayout());

            (..)

                browse = new JButton("Choose file");
                browse.setActionCommand("browse");
                browse.addActionListener(this);
                gbc.gridx = 1;
                gbc.gridy = 2;
                gbc.insets = new Insets(0,0,0,0);
                toppane.add(browse,gbc);

                gbc.gridx = 2;
                gbc.gridy = 2;
                gbc.insets = new Insets(0,5,0,0);
                toppane.add(userfile,gbc);

        add(toppane, BorderLayout.NORTH);

        JPanel midpane = new JPanel();
        midpane.setLayout(new GridBagLayout());
        add(midpane, BorderLayout.CENTER);

            (..)
}

@Override
public void actionPerformed(ActionEvent e) {

    if("browse".equalsIgnoreCase(e.getActionCommand())){

        final JFileChooser fc = new JFileChooser();
        fc.setFileFilter(new ExtensionFileFilter());
        int returnVal = fc.showOpenDialog(fc);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            file = fc.getSelectedFile();
            //This is where a real application would open the file.
            userfile.setText(file.getName());
            userBgPath = file.getPath();

            // THIS IS WHERE I UPDATE PATH etc.
            MainFrame.bg.setPath(userBgPath);
            MainFrame.bg.defaultbgset = false; // set to user
            MainFrame.bg.repaint();
            MainFrame.bg.revalidate();
            user_bg.setSelected(true);
            System.out.println("File: " + file.getName() + ".");    
        } else {

            MainFrame.bg.defaultbgset = true;
            MainFrame.bg.resetPath();
            MainFrame.bg.repaint();
            MainFrame.bg.revalidate();
            default_bg.setSelected(true);
        }
    } // end of if

}

public static String getPath(){

    return userBgPath;
}
}
现在是
GUISettings
类:

public class ImagePanel extends JPanel{

private String defaultbg = "Icons/background.jpg";
private String path = "";
private BufferedImage img;
private GridBagConstraints gbc = new GridBagConstraints();
public ImageIcon bgicon;
private Image bg;
public static boolean defaultbgset = true;


public ImagePanel(){

    if(defaultbgset){

        path = defaultbg;
        System.out.println("path in default = " + path);
    } else {

        if(GUISettings.getPath() != null){

            path = GUISettings.getPath();
            System.out.println("path in userBG = " + path);
        }
    }

    bgicon = new ImageIcon(getClass().getResource(path));

    bg = (new ImageIcon(bgicon.getImage().getScaledInstance(1024, 800, java.awt.Image.SCALE_SMOOTH))).getImage();
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
}

public ImageIcon getDrawBoardBackground(){

    return bgicon;
}

public void setPath(String p){

    this.path = p;
}

public void resetPath(){

    this.path = defaultbg;
}

}
public class GUISettings extends JPanel implements ActionListener{


private TitledBorder title = BorderFactory.createTitledBorder("User Interface Settings");
private JLabel lbackground, userbg;
private JTextField bgpath;
private GridBagConstraints gbc = new GridBagConstraints();
public static JRadioButton default_bg, user_bg;
private JButton browse;
public static File file;
private JLabel userfile = new JLabel("Not chosen.");

public static String userBgPath = null; 

public GUISettings(){

    //this.setLayout(new GridBagLayout());
    Dimension size = getPreferredSize();
    size.setSize(200,150); //w, h
    this.setPreferredSize(size);
    this.setBorder(title);

    JPanel toppane = new JPanel();
    toppane.setLayout(new GridBagLayout());

            (..)

                browse = new JButton("Choose file");
                browse.setActionCommand("browse");
                browse.addActionListener(this);
                gbc.gridx = 1;
                gbc.gridy = 2;
                gbc.insets = new Insets(0,0,0,0);
                toppane.add(browse,gbc);

                gbc.gridx = 2;
                gbc.gridy = 2;
                gbc.insets = new Insets(0,5,0,0);
                toppane.add(userfile,gbc);

        add(toppane, BorderLayout.NORTH);

        JPanel midpane = new JPanel();
        midpane.setLayout(new GridBagLayout());
        add(midpane, BorderLayout.CENTER);

            (..)
}

@Override
public void actionPerformed(ActionEvent e) {

    if("browse".equalsIgnoreCase(e.getActionCommand())){

        final JFileChooser fc = new JFileChooser();
        fc.setFileFilter(new ExtensionFileFilter());
        int returnVal = fc.showOpenDialog(fc);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            file = fc.getSelectedFile();
            //This is where a real application would open the file.
            userfile.setText(file.getName());
            userBgPath = file.getPath();

            // THIS IS WHERE I UPDATE PATH etc.
            MainFrame.bg.setPath(userBgPath);
            MainFrame.bg.defaultbgset = false; // set to user
            MainFrame.bg.repaint();
            MainFrame.bg.revalidate();
            user_bg.setSelected(true);
            System.out.println("File: " + file.getName() + ".");    
        } else {

            MainFrame.bg.defaultbgset = true;
            MainFrame.bg.resetPath();
            MainFrame.bg.repaint();
            MainFrame.bg.revalidate();
            default_bg.setSelected(true);
        }
    } // end of if

}

public static String getPath(){

    return userBgPath;
}
}
这应写为:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
}
无论何时您以任何方式更改ImagePanel的图像,都必须调用
ImagePanel
对象的
repaint()
方法(比如ImagePanel)。。使用
imagePanel.repaint()

更新
在我看来,您应该在
ImagePanel
类中有一个方法,您可以在其中设置图像并重新绘制
JPanel
本身,如下所示:

public void setImage(Image bg)
{
  this.bg = bg;
  repaint();
}
这将避免您在使用对象的位置显式调用
ImagePanel
对象的
repaint()
方法

这应写为:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
}
无论何时您以任何方式更改ImagePanel的图像,都必须调用
ImagePanel
对象的
repaint()
方法(比如ImagePanel)。。使用
imagePanel.repaint()

更新
在我看来,您应该在
ImagePanel
类中有一个方法,您可以在其中设置图像并重新绘制
JPanel
本身,如下所示:

public void setImage(Image bg)
{
  this.bg = bg;
  repaint();
}
这将避免您在使用对象的位置显式调用
ImagePanel
对象的
repaint()
方法

然后将file.getPath()字符串传递给ImagePanel类

通过这条路没有任何作用。当路径改变时,您实际上需要读取图像。因此,在set path方法中,我想您需要添加如下代码:

bgicon = new ImageIcon(getClass().getResource(path));
bg = (new ImageIcon(bgicon.getImage().getScaledInstance(1024, 800, java.awt.Image.SCALE_SMOOTH))).getImage();
repaint();
这个类应该负责自己重新绘制

然后将file.getPath()字符串传递给ImagePanel类

通过这条路没有任何作用。当路径改变时,您实际上需要读取图像。因此,在set path方法中,我想您需要添加如下代码:

bgicon = new ImageIcon(getClass().getResource(path));
bg = (new ImageIcon(bgicon.getImage().getScaledInstance(1024, 800, java.awt.Image.SCALE_SMOOTH))).getImage();
repaint();

班级应该负责自己重新粉刷。

是的,这确实完成了任务!谢谢+1尽管我不是第一个鼓励使用
getScaledInstance
的人。看看推理的答案。是的,这确实起到了作用!谢谢+1尽管我不是第一个鼓励使用
getScaledInstance
的人。参见推理答案。