Search code examples
javaswingjpanelbackground-imagepaintcomponent

Cant update background of JPanel using paintComponent to set its background


I'm making an application where you can change your background to any picture or just leave the default one. It consists of a ImagePanel class that overides its paintComponent to set a imageicon as its background.

  • What I'm trying to do is from GUISettings class for the user to choose an image from a FileChooser with a filter and then pass the file.getPath() string to the ImagePanel class and revalidate that gui, but no background is changed, not even the debug prints that I have in ImagePanel show on console.

The following is the code (simplified):

The ImagePanel class:

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

}

Now the GUISettings class:

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

Solution

  • then pass the file.getPath() string to the ImagePanel class

    Passing the path doesn't do anything. You actually need to read the image when the path changes. So in your set path method I would guess you need to add code like:

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

    The class should be responsible for repainting itself.