Java:保持 JPanel 背景图像的纵横比 [英] Java: maintaining aspect ratio of JPanel background image

查看:25
本文介绍了Java:保持 JPanel 背景图像的纵横比的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有绘制背景图像的 JPanel 和一个包含其他较小图像的布局管理器,所有这些都在 JFrame 中.背景图像非常大,我希望无论是在大显示器还是小显示器上都能保持其纵横比.

最终,我希望能够将我的 LayoutManager 及其单元格中的较小图像粘"到背景图片上.

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

public class MonitorPanel extends JPanel {图片 img;public MonitorPanel() 抛出 MalformedURLException {//添加组件尝试 {img = ImageIO.read(new File("src/customer_vlans.jpg"));} catch (IOException e) {//TODO 自动生成的 catch 块e.printStackTrace();}}protected voidpaintComponent(Graphics g){//绘制背景图像super.paintComponent(g);//g.drawImage(img, 0, 0, getWidth(), getHeight(), this);g.drawImage(img, 0, 0, this);}}

<小时>

我应该提到我知道纵横比公式:原始高度/原始宽度 x 新宽度 = 新高度但是,我不知道如何正确使用它来为我带来好处.

解决方案

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

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

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

<块引用>

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

更新

作为旁注(我的谷歌正在播放).

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

阅读Image.getScaledInstance 的危险,了解更多想法>

更新

缩放图像以适应某个区域比简单地缩放纵横比稍微复杂一些.您必须选择是否希望图像适合"区域内(可能在其周围留下空白区域)或过度填充"区域(使其最小尺寸适合区域的最大尺寸).

适合&填写

基本上,我使用比例因子

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

public static double getScaleFactor(int iMasterSize, int iTargetSize) {双 dScale = 1;如果(iMasterSize > iTargetSize){dScale = (double) iTargetSize/(double) iMasterSize;} 别的 {dScale = (double) iTargetSize/(double) iMasterSize;}返回 dScale;}

这两种方法都用到了.他们只需要两个Dimension.原始和目标.

public static double getScaleFactorToFit(Dimension original, Dimension toFit) {双 dScale = 1d;如果(原始!= null && toFit != null){double dScaleWidth = getScaleFactor(original.width, toFit.width);double dScaleHeight = getScaleFactor(original.height, toFit.height);dScale = Math.min(dScaleHeight, dScaleWidth);}返回 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);返回 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) {双 dScale = 1;如果(iMasterSize > iTargetSize){dScale = (double) iTargetSize/(double) iMasterSize;} 别的 {dScale = (double) iTargetSize/(double) iMasterSize;}返回 dScale;}公共双getScaleFactorToFit(尺寸原始,尺寸适合){双 dScale = 1d;如果(原始!= null && toFit != null){double dScaleWidth = getScaleFactor(original.width, toFit.width);double dScaleHeight = getScaleFactor(original.height, toFit.height);dScale = Math.min(dScaleHeight, dScaleWidth);}返回 dScale;}@覆盖受保护的无效paintComponent(图形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.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);}

I have a JPanel with a painted background image and a layout manager holding other smaller images, all of this inside a JFrame. The background image is pretty big and I want to be able to have it maintain its aspect ratio whether its on a big or small monitor.

Eventually, I want to be able to have my LayoutManager and the smaller images in its cells "glued" to the background picture.

I looked around for resources and it seems that many examples use a BufferedImage but I am not; will this pose a problem? I'll post my code below for painting the image, If I lack any information please let me know.

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: I should mention that I know the aspect ratio formula: original height / original width x new width = new height However, I do not know how to use that correctly to my advantage.

解决方案

Well, the quickest and easiest solution is to use Image.getScaledInstance

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

If your wondering about the negative number, the java docs say:

If either width or height is a negative number then a value is substituted to maintain the aspect ratio of the original image dimensions. If both width and height are negative, then the original image dimensions are used.

UPDATE

Just as a side note (my Google was playing up).

getScaledInstance is neither the fastest or highest quality approach, but it is the easiest.

Take a read through The Perils of Image.getScaledInstance for some more ideas

UPDATE

Scaling an image to fit an area is slightly more complicated then simply scaling the aspect ratio. You have to make a choice over if you want the image to "fit" within the area (possibly leaving blank areas around it) or over "fill" the area (so that it's smallest dimension fits the largest dimension of the area).

Fit & Fill

Basically, I work with scale factors

This returns the scaling factor for a particular size. I use this to make decisions about which factor I want to use based which algorithm I need

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;

}

It's used by these two methods. They simply take two Dimensions. The original and the target.

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;

}

It's relatively simple to pass an image into (either directly or via a support method). So for example, you could call this from within your paint method

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

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

This will automatically take care of the aspect ratio for you ;)

UPDATED with expanded example

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

}

这篇关于Java:保持 JPanel 背景图像的纵横比的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆