Java:维护JPanel背景图像的纵横比

exi*_*t_1 19 java swing background-image jpanel aspect-ratio

我有一个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);

}

}
Run Code Online (Sandbox Code Playgroud)

编辑:我应该提到我知道宽高比公式: 原始高度/原始宽度x新宽度=新高度 然而,我不知道如何正确使用它对我有利.

Mad*_*mer 44

那么,最快捷,最简单的解决方案就是使用 Image.getScaledInstance

g.drawImage(img.getScaledInstance(newWidth, -1, Image. SCALE_SMOOTH), x, y, this);
Run Code Online (Sandbox Code Playgroud)

如果您对负数感到疑惑,那么java文档会说:

如果宽度或高度是负数,则替换值以保持原始图像尺寸的纵横比.如果宽度和高度都为负,则使用原始图像尺寸.

UPDATE

就像一个旁注(我的谷歌正在播放).

getScaledInstance 既不是最快或最高质量的方法,但它是最简单的方法.

阅读Image.getScaledInstance的Perils阅读更多想法

UPDATE

缩放图像以适合某个区域比仅缩放纵横比稍微复杂一些.如果您希望图像在区域内"适合"(可能在其周围留下空白区域)或"填充"该区域(以使其最小尺寸适合该区域的最大尺寸),则必须做出选择.

适合填

适合和填充

基本上,我使用比例因子

这将返回特定大小的缩放系数.我用它根据我需要的算法决定我想要使用哪个因素

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;

}
Run Code Online (Sandbox Code Playgroud)

它被这两种方法使用.他们只需要两个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;

}
Run Code Online (Sandbox Code Playgroud)

将图像传入(直接或通过支持方法)相对简单.例如,您可以在paint方法中调用它

double factor getScaledFactorToFit(new Dimension(image.getWidth(), image.getHeight()), getSize());

int scaledWidth = image.getWidth() * scale;
int scaledHeight *= image.getWidth() * scale;
Run Code Online (Sandbox Code Playgroud)

这将自动为您处理宽高比;)

更新了扩展示例

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

}
Run Code Online (Sandbox Code Playgroud)