如何在JPanel中设置背景图片 [英] How to set a background picture in JPanel
问题描述
你好我使用JPanel作为我框架的容器然后我真的想在我的面板中使用背景图片我真的需要帮助这是我的代码到目前为止。这是更新,请点击这里查看我现在的代码
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
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);
}
}
}
推荐答案
可以通过多种方式实现这一目标。
There are any number of ways this might be achieved.
为此目的使用 JLabel
进行封锁可能导致内容超过溢出合并者,请参阅下文了解更多详情
Cavet, using a JLabel
for this purpose may result in the contents over spilling the continer, see below for more details
创建 JLabel
,将图像应用于其中 icon
属性并将其设置为框架内容窗格。然后你需要适当地设置布局管理器,因为 JLabel
没有默认布局管理器
Create a JLabel
, apply the image to it's icon
property and set this as the frames content pane. You would then need to set the layout manager appropriately, as JLabel
doesn't have a default layout manager
JFrame frame = ...;
JLabel background = new JLabel(new ImageIcon(ImageIO.read(...)));
frame.setContentPane(background);
frame.setLayout(...);
frame.add(...);
使用完整示例进行更新
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 JLabel
won't resize the image when the frame is resized
警告 - 使用<$ c $如果子组件的所需空间超过背景图像的大小,则c> JLabel 可能会导致问题,因为 JLabel
不计算它的首选大小基于它的内容,但基于其图标
和文本
属性
WARNING - Using a JLabel
could cause issues if the required space of the child components exceeds the size of the background image, as JLabel
does not calculate it's preferred size based on it's contents, but based on its icon
and text
properties
创建一个自定义组件,从 JPanel
扩展并覆盖它 paintComponent
方法,根据需要绘制背景。
Create a custom component, extending from something like JPanel
and override it's paintComponent
method, painting the background as you see fit.
看看执行自定义绘画以获取更多详细信息。
Take a look at Performing Custom Painting for more details.
这使您能够决定图像在缩放时的最佳缩放程度可用空间变化。虽然有很多方法可以实现,但您应该阅读 Image.getScaledInstance()的危险,以了解它们的优点和缺点。
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.
这引起了一堆对于你想要缩放它们并保持纵横比的新问题?如果是这样,你想让图像适合可用区域还是填充它(因此它总是覆盖可用空间)?
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)?
看看Java:维护JPanel背景图片的宽高比了解更多详情。
其他注意事项
图像通常最好通过<$ c加载$ c> ImageIO API,因为它能够加载各种图像,但在出现问题时也会抛出 IOException
。
Images are generally best loaded through the ImageIO
API, as it's capable of loading a wide range of images, but will also throw an IOException
when something goes wrong.
请参阅阅读/加载图片以获取更多详细信息。
See Reading/Loading an Image for more details.
图像的位置也很重要。如果映像在应用程序外部(文件系统的某个位置),则可以使用 ImageIO.read(新文件(/ path / to / image))
。但是,如果图像嵌入在您的应用程序中(例如存储在Jar中),则需要使用更像 ImageIO.read(getClass()。getResource(/ path / to /)的内容。图像))
而不是...
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...
例如......
- Trouble Figuring Out How To Set Background Image
- Add an Background image to a Panel
- Java: JPanel background not scaling
示例
此示例演示如何使用充当背景组件的自定义组件。当组件大小超过背景图像的大小时,图像将按比例放大以填充可用内容区域。
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.
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.
这个例子也利用了自定义的划分和征服缩放algrotithm以生成高质量的缩放结果。
The example also makes use of a custom divide and conquer scaling algrotithm in order to generate a high quality scaled result.
这篇关于如何在JPanel中设置背景图片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!