I am using a quite basic setup with a class extending JPanel, which I add to a JFrame. 
import java.awt.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.event.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.*;
import java.io.*;
import javax.imageio.ImageIO;
public class PinTestMCVE extends JPanel implements ActionListener{
    BufferedImage loadedImage;
    JButton calcButton;
    public static void main(String[] args) {
        new PinTestMCVE();
    }
    public PinTestMCVE() {
        loadedImage = getTestImage();
        JPanel toolbarPanel = new JPanel();
        calcButton = new JButton("calcButton...");
        toolbarPanel.add(calcButton);
        calcButton.addActionListener(this);
        JFrame jf = new JFrame();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.getContentPane().setLayout(new BorderLayout()); 
        jf.getContentPane().add(toolbarPanel, BorderLayout.NORTH);
        jf.getContentPane().add(this, BorderLayout.CENTER);
        jf.setSize(1250, 950);
        jf.setVisible(true);
    }
    public void paintComponent(Graphics g) {
        g.drawImage(loadedImage, 0, 0, this);
    }
    public void actionPerformed(ActionEvent e) {
        System.out.println("ActionEvent " + e.getActionCommand());
        if(e.getSource().equals(calcButton)){
            this.repaint();
        }
    }
//Please ignore the inner workings of this
public static BufferedImage getTestImage(){
    BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = image.createGraphics();
    g2d.setPaint(Color.GRAY);
    g2d.fillRect ( 0, 0, image.getWidth(), image.getHeight() );
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setPaint(Color.gray);
    int x = 5;
    int y = 7;
    GradientPaint redtowhite = new GradientPaint(x, y, Color.red, 200, y, Color.blue);
    g2d.setPaint(redtowhite);
    g2d.fill(new RoundRectangle2D.Double(x, y, 200, 200, 10, 10));
    return image;
}
}
What happens is that INITIALLY the window is painted properly, but once paintComponent is called, a strip of the old image (with the same height as the toolbar panel) is visible below the newly painted images - similar to playing card sticking out from a deck. But then, if I manually resize the window by for instance dragging the border, the background is grayed out as it should.
What is going on and how do I fix this?
 
     
    
 
    