简体   繁体   English

调整大小后,JPanel背景图像无法填充面板

[英]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. 我正在尝试调整背景图像的大小,以使其始终适合其所驻留的JPanel。 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? 如何绘制图像并填充整个JPanel?

The problem is, the scaledImage 's size is not being changed on subsequent rescales. 问题是, scaledImage的大小在后续scaledImage不会更改。

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) 这是因为您将scaledImage的引用传递给filter方法,该方法将其用作结果操作的基础,而不是生成新图像(大小合适)

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 它第一次起作用的原因是因为scaledImagenull开头

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). 随着您增加框架的大小,在绘制面板背景之前,先导边缘上会绘制黑色背景(我在Windows 7上使用JDK7_10)。 Shrinking the frame doesn't cause a problem. 缩小框架不会造成问题。 I think this is because of the ComponentListener and the recreation of the image. 我认为这是由于ComponentListener和图像的重新生成。

There is no need for the ComponentListener. 不需要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. 不知道图像质量是否相同,因为我不知道BILINEAR会做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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