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

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

问题描述

我有一张带有彩绘背景图片的 JPanel 和一张包含其他小图片的布局管理器,所有这些都在 JFrame 。背景图像非常大,我希望它能够保持其宽高比,无论是在大型还是小型显示器上。



最终,我希望能够拥有 LayoutManager ,并且其单元格中的较小图像粘合到背景图片。



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

 公共类MonitorPanel扩展JPanel {
Image img;
public MonitorPanel()抛出MalformedURLException {
//添加组件

try {
img = ImageIO.read(new File(src / customer_vlans.jpg)) );
} catch(IOException e){
// TODO自动生成的catch块
e.printStackTrace();
}

}
protected void paintComponent(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文档会说:


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


UPDATE



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



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



读取 Image.getScaledInstance的危险以获取更多想法



更新



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



Fit&填充



基本上,我使用比例因子



这将返回特定大小的比例因子。我用它根据我需要的算法决定我想要使用哪个因素

  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;

}

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

}

返回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){

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

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

} else {

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

}

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

}

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

}


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天全站免登陆