简体   繁体   中英

JPanel background image not filling panel after resize

I am trying to make the background image resize to always fit the JPanel in which it resides. When the program is ran it looks purrfect:

在此处输入图片说明

The problem I'm having is that after I resize the window it looks like so:

在此处输入图片说明

Obviously, the image is resizing but it isn't being fully drawn for some reason. This is part of a much larger application, but I have isolated the smallest subset of code that creates the problem:

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.*;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.*;

public class ScaleTest extends JPanel {
static JFrame window;
static JPanel mainPanel;

BufferedImage originalImage;
BufferedImage scaledImage;

ScaleTest() {
    setPreferredSize(new Dimension(320, 200));
    try {
        originalImage = ImageIO.read(new File("cat.jpg"));
    } catch(Exception e){}

    addComponentListener(new ResizerListener());
}

public void resize() {
    double widthScaleFactor = getWidth() / (double)originalImage.getWidth();
    double heightScaleFactor = getHeight() / (double)originalImage.getHeight();
    double scaleFactor = (widthScaleFactor > heightScaleFactor)? heightScaleFactor : widthScaleFactor;

    AffineTransform at = new AffineTransform();
    at.scale(scaleFactor, scaleFactor);

    AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
    scaledImage = scaleOp.filter(originalImage, scaledImage);

    repaint();
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);

    g.drawImage(scaledImage, 0, 0, null);
}

public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run(){
            window = new JFrame("Scale Test");
            window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

            mainPanel = new ScaleTest();
            window.getContentPane().add(mainPanel);

            window.pack();
            window.setLocationRelativeTo(null);  // positions window in center of screen
            window.setVisible(true);
        }
    });
}

class ResizerListener implements ComponentListener {
    @Override
    public void componentResized(ComponentEvent e) {
        resize();
    }

    @Override public void componentHidden(ComponentEvent e) {}
    @Override public void componentMoved(ComponentEvent e) {}
    @Override public void componentShown(ComponentEvent e) {}
}
}

How can I make the image draw and fill the entire JPanel?

The problem is, the scaledImage 's size is not being changed on subsequent rescales.

This is because you are passing a reference of the scaledImage to the filter method, which is using that as the bases for the resulting operation, rather then generating a new image (at the right size)

Instead of

scaledImage = scaleOp.filter(originalImage, scaledImage);

Try using

scaledImage = scaleOp.filter(originalImage, null);

The reason it works the first time is because scaledImage is null to start with

When I try the code with the suggested change I find the repainting a bit choppy. As you increase the size of the frame a black background is painted on the leading edge before the panels background is painted (I'm using JDK7_10 on Windows 7). Shrinking the frame doesn't cause a problem. I think this is because of the ComponentListener and the recreation of the image.

There is no need for the ComponentListener. You can resize the image on the fly with code like the following:

super.paintComponent(g);

double widthScaleFactor = getWidth() / (double)originalImage.getWidth();
double heightScaleFactor = getHeight() / (double)originalImage.getHeight();
double scaleFactor = (widthScaleFactor > heightScaleFactor)? heightScaleFactor : widthScaleFactor;

int width = (int)(originalImage.getWidth() * scaleFactor);
int height = (int)(originalImage.getHeight() * scaleFactor);

g.drawImage(originalImage, 0, 0, width, height, null);

Don't know if the image quality is the same because I don't know what BILINEAR does.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM