Java 如何在JPanel中设置背景图片

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22162398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 14:00:02  来源:igfitidea点击:

How to set a background picture in JPanel

javaimageswinguser-interfacejpanel

提问by Batusai

hello i am using JPanel as my container of my frame then i really want to used a background picture in my Panel i really need help this is my code so far . this is the updates please check here is my code now

你好,我使用 JPanel 作为我的框架的容器然后我真的想在我的面板中使用背景图片我真的需要帮助这是我的代码到目前为止。这是更新,请检查这里是我的代码

 import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


public class imagebut extends JFrame
{

public static void main(String args [])
{
    imagebut w = new imagebut();
    w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    w.setSize(300,300);
    w.setVisible(true);

}
public imagebut()
{   

    setLayout(null); // :-)
    PicPanel mainPanel = new PicPanel("picturename.jpg");
    mainPanel.setBounds(0,0,500,500);
    add(mainPanel);


}

class PicPanel extends JPanel{

    private BufferedImage image;
    private int w,h;
    public PicPanel(String fname){

        //reads the image
        try {
            image = ImageIO.read(new File(fname));
            w = image.getWidth();
            h = image.getHeight();

        } catch (IOException ioe) {
            System.out.println("Could not read in the pic");
            //System.exit(0);
        }

    }

    public Dimension getPreferredSize() {
        return new Dimension(w,h);
    }
    //this will draw the image
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(image,0,0,this);
    }
}

}

采纳答案by MadProgrammer

There are any number of ways this might be achieved.

有多种方法可以实现这一点。

You Could...

你可以...

Disclaimer

免责声明

Cavet, using a JLabelfor this purpose may result in the contents over spilling the continer, see below for more details

Cavet,JLabel为此目的使用 a可能会导致内容物溢出容器,有关详细信息,请参见下文

Create a JLabel, apply the image to it's iconproperty and set this as the frames content pane. You would then need to set the layout manager appropriately, as JLabeldoesn't have a default layout manager

创建一个JLabel,将图像应用于其icon属性并将其设置为框架内容窗格。然后您需要适当地设置布局管理器,因为JLabel没有默认的布局管理器

JFrame frame = ...;
JLabel background = new JLabel(new ImageIcon(ImageIO.read(...)));
frame.setContentPane(background);
frame.setLayout(...);
frame.add(...);

Update with full example

使用完整示例更新

label based example

基于标签的例子

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class LabelBackground {

    public static void main(String[] args) {
        new LabelBackground();
    }

    public LabelBackground() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    // Load the background image
                    BufferedImage img = ImageIO.read(new File("/path/to/your/image/on/disk"));

                    // Create the frame...
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                    // Set the frames content pane to use a JLabel
                    // whose icon property has been set to use the image
                    // we just loaded                        
                    frame.setContentPane(new JLabel(new ImageIcon(img)));

                    // Supply a layout manager for the body of the content
                    frame.setLayout(new GridBagLayout());
                    GridBagConstraints gbc = new GridBagConstraints();
                    gbc.gridwidth = GridBagConstraints.REMAINDER;
                    // Add stuff...
                    frame.add(new JLabel("Hello world"), gbc);
                    frame.add(new JLabel("I'm on top"), gbc);
                    frame.add(new JButton("Clickity-clackity"), gbc);

                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }
}

The problem with this is the JLabelwon't resize the image when the frame is resized

这个问题是在JLabel调整框架大小时不会调整图像大小

WARNING- Using a JLabelcould cause issues if the required space of the child components exceeds the size of the background image, as JLabeldoes not calculate it's preferred size based on it's contents, but based on its iconand textproperties

警告-JLabel如果子组件所需的空间超过背景图像的大小,则使用 a可能会导致问题,因为JLabel不会根据其内容计算其首选大小,而是根据其icontext属性

You Could...

你可以...

Create a custom component, extending from something like JPaneland override it's paintComponentmethod, painting the background as you see fit.

创建一个自定义组件,从类似的东西扩展JPanel并覆盖它的paintComponent方法,根据您的需要绘制背景。

Take a look at Performing Custom Paintingfor more details.

有关更多详细信息,请查看执行自定义绘画

This provides you with the ability to decide how best the image should be scaled when it's available space changes. While there are a number of ways this might be achived, you should read through The Perils of Image.getScaledInstance()to understand the pros and cons of them.

这使您能够决定在可用空间发生变化时如何最好地缩放图像。虽然有多种方法可以实现这一点,但您应该通读Image.getScaledInstance() 的危险以了解它们的优缺点。

This raises a bunch of new questions, to you want to scale them and preserve the aspect ratio? If so, do you want to fit the image to available area or fill it (so it will always cover the available space)?

这引发了一系列新问题,您想缩放它们并保持纵横比吗?如果是这样,您是要使图像适合可用区域还是填充它(以便它始终覆盖可用空间)?

Take a look at Java: maintaining aspect ratio of JPanel background imagefor more details.

看看Java:保持JPanel背景图像的纵横比以获取更多详细信息。

Other considerations

其他注意事项

Images are generally best loaded through the ImageIOAPI, as it's capable of loading a wide range of images, but will also throw an IOExceptionwhen something goes wrong.

图像通常最好通过ImageIOAPI加载,因为它能够加载范围广泛的图像,但也会IOException在出现问题时抛出。

See Reading/Loading an Imagefor more details.

有关更多详细信息,请参阅读取/加载图像

The location of the image is also important. If the image is external to the application (somewhere on the file system), you can use ImageIO.read(new File("/path/to/image")). However, if the the image is embedded within your application (stored within the Jar for example), you will need to use something more like ImageIO.read(getClass().getResource("/path/to/image"))instead...

图像的位置也很重要。如果图像在应用程序外部(文件系统上的某处),您可以使用ImageIO.read(new File("/path/to/image")). 但是,如果图像嵌入在您的应用程序中(例如存储在 Jar 中),您将需要使用更像ImageIO.read(getClass().getResource("/path/to/image"))...

For example...

例如...

Example

例子

This example demonstrates the use of a custom component which acts as the background component. When the components size exceeds the size of the background image, the image is scaled up to fill the available content area.

此示例演示如何使用用作后台组件的自定义组件。当组件大小超过背景图像的大小时,图像会被放大以填充可用的内容区域。

enter image description here

在此处输入图片说明

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SimpleBackground {

    public static void main(String[] args) {
        new SimpleBackground();
    }

    public SimpleBackground() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    BackgroundPane background = new BackgroundPane();
                    background.setBackground(ImageIO.read(new File("/path/to/your/image/on/your/disk")));

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setContentPane(background);
                    frame.setLayout(new GridBagLayout());
                    GridBagConstraints gbc = new GridBagConstraints();
                    gbc.gridwidth = GridBagConstraints.REMAINDER;
                    frame.add(new JLabel("Hello world"), gbc);
                    frame.add(new JLabel("I'm on top"), gbc);
                    frame.add(new JButton("Clickity-clackity"), gbc);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    public class BackgroundPane extends JPanel {

        private BufferedImage img;
        private BufferedImage scaled;

        public BackgroundPane() {
        }

        @Override
        public Dimension getPreferredSize() {
            return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(), img.getHeight());
        }

        public void setBackground(BufferedImage value) {
            if (value != img) {
                this.img = value;
                repaint();
            }
        }

        @Override
        public void invalidate() {
            super.invalidate();
            if (getWidth() > img.getWidth() || getHeight() > img.getHeight()) {
                scaled = getScaledInstanceToFill(img, getSize());
            } else {
                scaled = img;
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (scaled != null) {
                int x = (getWidth() - scaled.getWidth()) / 2;
                int y = (getHeight() - scaled.getHeight()) / 2;
                g.drawImage(scaled, x, y, this);
            }
        }

    }

    public static BufferedImage getScaledInstanceToFill(BufferedImage img, Dimension size) {

        double scaleFactor = getScaleFactorToFill(img, size);

        return getScaledInstance(img, scaleFactor);

    }

    public static double getScaleFactorToFill(BufferedImage img, Dimension size) {

        double dScale = 1;

        if (img != null) {

            int imageWidth = img.getWidth();
            int imageHeight = img.getHeight();

            double dScaleWidth = getScaleFactor(imageWidth, size.width);
            double dScaleHeight = getScaleFactor(imageHeight, size.height);

            dScale = Math.max(dScaleHeight, dScaleWidth);

        }

        return dScale;

    }

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

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

        return dScale;

    }

    public static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor) {

        return getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);

    }

    protected static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint, boolean bHighQuality) {

        BufferedImage imgScale = img;

        int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor);
        int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor);

//        System.out.println("Scale Size = " + iImageWidth + "x" + iImageHeight);
        if (dScaleFactor <= 1.0d) {

            imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint, bHighQuality);

        } else {

            imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint, bHighQuality);

        }

        return imgScale;

    }

    protected static BufferedImage getScaledDownInstance(BufferedImage img,
            int targetWidth,
            int targetHeight,
            Object hint,
            boolean higherQuality) {

        int type = (img.getTransparency() == Transparency.OPAQUE)
                ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;

        BufferedImage ret = (BufferedImage) img;
        if (targetHeight > 0 || targetWidth > 0) {
            int w, h;
            if (higherQuality) {
                // Use multi-step technique: start with original size, then
                // scale down in multiple passes with drawImage()
                // until the target size is reached
                w = img.getWidth();
                h = img.getHeight();
            } else {
                // Use one-step technique: scale directly from original
                // size to target size with a single drawImage() call
                w = targetWidth;
                h = targetHeight;
            }

            do {
                if (higherQuality && w > targetWidth) {
                    w /= 2;
                    if (w < targetWidth) {
                        w = targetWidth;
                    }
                }

                if (higherQuality && h > targetHeight) {
                    h /= 2;
                    if (h < targetHeight) {
                        h = targetHeight;
                    }
                }

                BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type);
                Graphics2D g2 = tmp.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
                g2.drawImage(ret, 0, 0, w, h, null);
                g2.dispose();

                ret = tmp;
            } while (w != targetWidth || h != targetHeight);
        } else {
            ret = new BufferedImage(1, 1, type);
        }
        return ret;
    }

    protected static BufferedImage getScaledUpInstance(BufferedImage img,
            int targetWidth,
            int targetHeight,
            Object hint,
            boolean higherQuality) {

        int type = BufferedImage.TYPE_INT_ARGB;

        BufferedImage ret = (BufferedImage) img;
        int w, h;
        if (higherQuality) {
            // Use multi-step technique: start with original size, then
            // scale down in multiple passes with drawImage()
            // until the target size is reached
            w = img.getWidth();
            h = img.getHeight();
        } else {
            // Use one-step technique: scale directly from original
            // size to target size with a single drawImage() call
            w = targetWidth;
            h = targetHeight;
        }

        do {
            if (higherQuality && w < targetWidth) {
                w *= 2;
                if (w > targetWidth) {
                    w = targetWidth;
                }
            }

            if (higherQuality && h < targetHeight) {
                h *= 2;
                if (h > targetHeight) {
                    h = targetHeight;
                }
            }

            BufferedImage tmp = new BufferedImage(w, h, type);
            Graphics2D g2 = tmp.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(ret, 0, 0, w, h, null);
            g2.dispose();

            ret = tmp;
            tmp = null;

        } while (w != targetWidth || h != targetHeight);
        return ret;
    }

}

It would be a simple matter to also have the image scaled down when the space decreases, but I deliberately decided to maintain the image at it's smallest size.

当空间减小时缩小图像也是一件简单的事情,但我故意决定将图像保持在最小尺寸。

The example also makes use of a custom divide and conquer scaling algrotithm in order to generate a high quality scaled result.

该示例还使用自定义的分而治之的缩放算法来生成高质量的缩放结果。

回答by Solace

import java.awt.*;

import javax.imageio.ImageIO;
import javax.swing.*;

import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


public class imagebut extends JFrame
{

public static void main(String args [])
{
imagebut w = new imagebut();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
w.setSize(300,300);
w.setVisible(true);

}
 public imagebut()
{   

setLayout(null); // :-)
PicPanel mainPanel = new PicPanel("picturename.jpg");
mainPanel.setBounds(0,0,500,500);
add(mainPanel);


  }

 class PicPanel extends JPanel{

private BufferedImage image;
private int w,h;
public PicPanel(String fname){

    //reads the image
    try {
        image = ImageIO.read(getClass().getResource(fname));
        w = image.getWidth();
        h = image.getHeight();

    } catch (IOException ioe) {
        System.out.println("Could not read in the pic");
        //System.exit(0);
    }

}

public Dimension getPreferredSize() {
    return new Dimension(w,h);
}
//this will draw the image
public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.drawImage(image,0,0,this);
}
}

 }

回答by java-love

JPanel ping = new JPanel(){

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

//draw hare what ever you want and it will be in the back of your components
   }
};