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

Java:维护JPanel背景图像的纵横比,java,swing,jpanel,background-image,aspect-ratio,Java,Swing,Jpanel,Background Image,Aspect Ratio,我有一个JPanel,它有一个绘制的背景图像和一个布局管理器,其中包含其他较小的图像,所有这些都在JFrame中。背景图像非常大,我希望它能够保持其纵横比,无论是在大屏幕还是小屏幕上 最后,我希望能够将我的LayoutManager及其单元格中的较小图像“粘贴”到背景图片上 我四处寻找资源,似乎许多示例都使用了缓冲图像,但我没有;这会造成问题吗?我将在下面发布我的代码来绘制图像,如果我缺少任何信息,请让我知道 public class MonitorPanel extends JPanel {

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

最后,我希望能够将我的
LayoutManager
及其单元格中的较小图像“粘贴”到背景图片上

我四处寻找资源,似乎许多示例都使用了
缓冲图像
,但我没有;这会造成问题吗?我将在下面发布我的代码来绘制图像,如果我缺少任何信息,请让我知道

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

}

}

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

试试这样的方法:

import java.awt.*;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class SG2B2 {

    JFrame frame;

    public static void main(String[] args) {
        SG2B2 gui = new SG2B2();
        gui.createUI();
    }

    public void createUI() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MyDrawPanel drawPanel = new MyDrawPanel();
        frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
        frame.setSize(300, 400);
        frame.setVisible(true);
    }

    class MyDrawPanel extends JPanel {

        Image image;
        private final String pic = "Logo.jpg";

        public MyDrawPanel() {
            image = new ImageIcon(pic).getImage();
            image = scaleImage(image);
        }

        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.drawImage(image, 0, 0, this);
        }

        private Image scaleImage(Image rawImage) {
            Image scaledImage = null;
            System.out.println("Scaling");
            try {
                int rawImageWidth = rawImage.getWidth(this);
                int rawImageHeight = rawImage.getHeight(this);
                int paneWidth = (int) getWidth();
                int paneHeight = (int) getHeight();
                System.out.println("Image W = " + rawImageWidth
                        + ", H = " + rawImageHeight
                        + "; Pane W = " + paneWidth
                        + ", H = " + paneHeight);
                // preserve the original ratio  
                float widthRatio = (float) rawImageWidth / (float) paneWidth;
                float heightRatio = (float) rawImageHeight / (float) paneHeight;
                int widthFactor = -1;
                int heightFactor = -1;
                if ((widthRatio > heightRatio) && (widthRatio > 1.0)) {
                    widthFactor = paneWidth;
                } else if ((heightRatio > widthRatio) && (heightRatio > 1.0)) {
                    heightFactor = paneHeight;
                }
                System.out.println("widthRatio = "
                        + String.format("%.3f", widthRatio)
                        + ", heightRatio = "
                        + String.format("%.3f", heightRatio));
                System.out.println("widthFactor = " + widthFactor
                        + ", heightFactor = " + heightFactor);
                if ((widthFactor < 0) && (heightFactor < 0)) {
                    scaledImage = rawImage;
                } else {
                    scaledImage = rawImage.getScaledInstance(widthFactor, heightFactor,
                            Image.SCALE_SMOOTH);
                    // load the new image, 'getScaledInstance' loads asynchronously  
                    MediaTracker tracker = new MediaTracker(this);
                    tracker.addImage(scaledImage, 0);
                    tracker.waitForID(0);
                }
            } catch (InterruptedException ie) {
                System.err.println("load interrupt: " + ie.getMessage());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return (scaledImage);
        }
    }
}
import java.awt.*;
导入javax.swing.ImageIcon;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
公共级SG2B2{
JFrame框架;
公共静态void main(字符串[]args){
SG2B2 gui=新的SG2B2();
createUI();
}
public void createUI(){
frame=新的JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyDrawPanel drawPanel=新建MyDrawPanel();
frame.getContentPane().add(BorderLayout.CENTER,drawPanel);
框架。设置尺寸(300400);
frame.setVisible(true);
}
类MyDrawPanel扩展了JPanel{
图像;
私有最终字符串pic=“Logo.jpg”;
公共事务委员会(){
image=newimageicon(pic).getImage();
图像=缩放图像(图像);
}
@凌驾
公共组件(图形g){
图形2d g2=(图形2d)g;
g2.drawImage(图像,0,0,this);
}
专用图像缩放图像(图像rawImage){
图像缩放图像=空;
System.out.println(“缩放”);
试一试{
int rawImageWidth=rawImage.getWidth(这个);
int rawImageHeight=rawImage.getHeight(此值);
int paneWidth=(int)getWidth();
int paneHeight=(int)getHeight();
System.out.println(“图像W=“+rawImageWidth
+“,H=“+rawImageHeight
+“窗格W=“+窗格宽度”
+“,H=“+paneHeight);
//保持原来的比例
浮动宽度比率=(浮动)RAWMAGEEWITH/(浮动)窗格宽度;
浮动高度比率=(浮动)原始图像高度/(浮动)窗格高度;
整数宽度因子=-1;
整数高度因子=-1;
如果((宽度比>高度比)和&(宽度比>1.0)){
宽度系数=平面宽度;
}否则如果((高度比>宽度比)和&(高度比>1.0)){
高度系数=面板高度;
}
System.out.println(“宽度比=”
+字符串格式(“%.3f”,宽度比)
+,高度比=
+格式(“%.3f”,高度比));
System.out.println(“widthFactor=“+widthFactor
+“,heightFactor=“+heightFactor”);
如果((宽度系数<0)和(&(高度系数<0)){
缩放图像=原始图像;
}否则{
ScaleImage=rawImage.getScaledInstance(宽度因子、高度因子、,
图像。缩放(平滑);
//加载新映像,“GetScaleInstance”异步加载
MediaTracker=新的MediaTracker(此);
tracker.addImage(scaledImage,0);
tracker.waitForID(0);
}
}捕获(中断异常ie){
System.err.println(“加载中断:+ie.getMessage());
}捕获(例外e){
e、 printStackTrace();
}
返回(缩放图像);
}
}
}

通过使用
getScaledInstance(int-width,int-height,ImageObserver io)
最终将图像缩放到
JPanel
的大小

g.drawImage(img.getScaledInstance(newWidth, -1, Image. SCALE_SMOOTH), x, y, this);
如果您想知道负数,java文档会说:

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

更新

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

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

通读一遍,了解更多的想法

更新

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

装填

基本上,我使用比例因子

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

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;

}
这两种方法都使用它。它们只需要两个
维度
s。原作和目标

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

}
        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) 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 - scaleWidth) / 2;
            int y = (height - scaleHeight) / 2;

            g2d.drawImage(image, x, y, scaleWidth, scaleHeight, this);

        }
public class ImageLabel extends JPanel {

    private Image image = null;

    public void setImage(Image img) {
        image = img;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        if (image != null) {

            int imgWidth, imgHeight;
            double contRatio = (double) getWidth() / (double) getHeight();
            double imgRatio =  (double) image.getWidth(this) / (double) image.getHeight(this);

            //width limited
            if(contRatio < imgRatio){
                imgWidth = getWidth();
                imgHeight = (int) (getWidth() / imgRatio);

            //height limited
            }else{
                imgWidth = (int) (getHeight() * imgRatio);
                imgHeight = getHeight();
            }

            //to center
            int x = (int) (((double) getWidth() / 2) - ((double) imgWidth / 2));
            int y = (int) (((double) getHeight()/ 2) - ((double) imgHeight / 2));

            g.drawImage(image, x, y, imgWidth, imgHeight, this);
        }
    }
}