Java:维护JPanel背景图像的宽高比

问题描述 投票:19回答:4

我有一个JPanel,带有一个绘制的背景图像,一个布局管理器保存着其他较小的图像,所有这些都放在JFrame中。背景图像非常大,我希望它能够在大型或小型显示器上保持其纵横比。

最终,我希望能够将我的LayoutManager和其单元格中的较小图像“粘合”到背景图片。

我四处寻找资源,似乎很多示例都使用了BufferedImage,但我没有使用;这会带来问题吗?我将在下面发布用于绘制图像的代码,如果我缺少任何信息,请告诉我。

public class MonitorPanel extends JPanel {
    Image img;
    public MonitorPanel() throws MalformedURLException {
        //add components

        try {
            img = ImageIO.read(new File("src/customer_vlans.jpg"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
protected void paintComponent(Graphics g)
{
    //paint background image
    super.paintComponent(g);
    //g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
    g.drawImage(img, 0, 0, this);

}

}

EDIT:我应该提到我知道纵横比公式:原始高度/原始宽度x新宽度=新高度但是,我不知道如何正确地使用它来发挥自己的优势。

java swing jpanel background-image aspect-ratio
4个回答
44
投票

嗯,最快最简单的解决方案是使用Image.getScaledInstance

g.drawImage(img.getScaledInstance(newWidth, -1, Image. SCALE_SMOOTH), x, y, this);

如果您想知道负数,则Java文档会说:

如果宽度或高度为负数,则值为替换以保持原始图像的长宽比尺寸。如果宽度和高度均为负数,则原始使用图像尺寸。

UPDATE

作为旁注(我的Google正在播放)。

getScaledInstance既不是最快的方法也不是最高质量的方法,但这是最简单的方法。

阅读The Perils of Image.getScaledInstance以获得更多建议

UPDATE

缩放图像以适合某个区域要稍微复杂一些,然后再简单地缩放纵横比即可。如果要让图像“适合”该区域(可能在其周围留有空白区域),或者要“填充”该区域(以使其最小尺寸适合该区域的最大尺寸),则必须做出选择。 >

“适合” “填充“

Fit&Fill

基本上,我使用比例因子

这将返回特定尺寸的缩放比例。我根据自己需要的算法来决定要使用的因素]

public static double getScaleFactor(int iMasterSize, int iTargetSize) {

    double dScale = 1;
    if (iMasterSize > iTargetSize) {

        dScale = (double) iTargetSize / (double) iMasterSize;

    } else {

        dScale = (double) iTargetSize / (double) iMasterSize;

    }

    return dScale;

}

被这两种方法使用。他们只需要两个Dimension。原件和目标。

public static double getScaleFactorToFit(Dimension original, Dimension toFit) {

    double dScale = 1d;

    if (original != null && toFit != null) {

        double dScaleWidth = getScaleFactor(original.width, toFit.width);
        double dScaleHeight = getScaleFactor(original.height, toFit.height);

        dScale = Math.min(dScaleHeight, dScaleWidth);

    }

    return dScale;

}

public static double getScaleFactorToFill(Dimension masterSize, Dimension targetSize) {

    double dScaleWidth = getScaleFactor(masterSize.width, targetSize.width);
    double dScaleHeight = getScaleFactor(masterSize.height, targetSize.height);

    double dScale = Math.max(dScaleHeight, dScaleWidth);

    return dScale;

}

直接或通过支持方法将图像传递到其中相对简单。因此,例如,您可以从paint方法

中调用此方法
double factor getScaledFactorToFit(new Dimension(image.getWidth(), image.getHeight()), getSize());

int scaledWidth = image.getWidth() * scale;
int scaledHeight *= image.getWidth() * scale;

这将自动为您照顾长宽比;)

使用扩展示例进行更新

public double getScaleFactor(int iMasterSize, int iTargetSize) {

    double dScale = 1;
    if (iMasterSize > iTargetSize) {

        dScale = (double) iTargetSize / (double) iMasterSize;

    } else {

        dScale = (double) iTargetSize / (double) iMasterSize;

    }

    return dScale;

}

public double getScaleFactorToFit(Dimension original, Dimension toFit) {

    double dScale = 1d;

    if (original != null && toFit != null) {

        double dScaleWidth = getScaleFactor(original.width, toFit.width);
        double dScaleHeight = getScaleFactor(original.height, toFit.height);

        dScale = Math.min(dScaleHeight, dScaleWidth);

    }

    return dScale;

}

@Override
protected void paintComponent(Graphics g) {

    super.paintComponent(g);

    double scaleFactor = Math.min(1d, getScaleFactorToFit(new Dimension(image.getWidth(), image.getHeight()), getSize()));

    int scaleWidth = (int) Math.round(image.getWidth() * scaleFactor);
    int scaleHeight = (int) Math.round(image.getHeight() * scaleFactor);

    Image scaled = image.getScaledInstance(scaleWidth, scaleHeight, Image.SCALE_SMOOTH);

    int width = getWidth() - 1;
    int height = getHeight() - 1;

    int x = (width - scaled.getWidth(this)) / 2;
    int y = (height - scaled.getHeight(this)) / 2;

    g.drawImage(scaled, x, y, this);

}

4
投票

尝试这样的事情:


2
投票

对于有兴趣按以下方式通过MadProgrammer修改PaintComponent方法的任何人都可以更快地更新显示内容


1
投票

我想出了这个解决方案:

© www.soinside.com 2019 - 2024. All rights reserved.