用JAVA写桌面程序,难免不了想写出美观的界面,这样一来为面板添加背景图片就少不了了。
添加背景图片,一般有两种方式(我指的是我所认识到的,如还有其它方式,请补充,不甚感激)。一是在JFrame中添加背景图片,二是在JPanel中添加背景图片。
先说JFrame的情况。JFrame在ContentPane(可使用getContentPane方法得到)之下还有一层Panel,即LayerPane。这一层Panel一般我们不会使用到它。所以可以将图片加载到这里。其中一个思路是,使用指定的图像new一个JLabel,然后把这个JLabel添加到LayerPane中。完成之后,由于swing中的Panel默认都是不透明的,所以我们还需要对其之上的面板设置为透明,调用的方法是其之上Panel的setOpaque方法,参数为false。代码如下:
/** * 设置 JFrame 对象背景。 * * 本方法对内容面板设置了透明属性,如果窗体中调用了setContentPane(), * 则本方法必须在其之后调用,以保证该属性有效。如果使用add(JPanel),则必须对 * 每个JPanel调用其setOpaque(false)方法,以使背景图片显示出来。 * * @param frame 将要设置的窗体对象 * @param img 作为背景的图片 */ public static void setBackgroundImage(JFrame frame, ImageIcon img) { JLabel imgLabel = new JLabel(img); imgLabel.setBounds(0, 0, img.getIconWidth(), img.getIconHeight()); // 下面函数的参数必须为Integer对象 frame.getLayeredPane().add(imgLabel, new Integer(Integer.MIN_VALUE)); Container cp = frame.getContentPane(); ((JPanel)cp).setOpaque(false); // 设置内容面板透明,使图片显示出来 }
注意,如果在写代码中时有多个Panel(JPanel继承自Panel)添加到JFrame中时,需要对每个Panel都调用setOpaque(false)。如果只有一个Panel添加,则可以其之后调用该方法。
另一种情况是对JPanel添加背景图片,这种情况可用于当我们的JFrame有多个JPanel而又必须对每个JPanel设置不同的图片时。对此可以写一个ImageJPanel,并继承JPanel,然后重写其中的paintComponent(Graphics g)方法,在方法中绘制图片。注意重写时不要写错,建议查JAVA的API文档,然后从上面复制。实现代码如下:
/* * @(#)ImageJPanel.java 0.1 2011-6-21 * Copyright 2006 DiaoxianSoft Development Team. All rights reserved. * DiaoxianSoft PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package easyJFC.demo; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Image; import java.awt.LayoutManager; import javax.swing.JPanel; /** * 带有图片背景的JPanel,图片起始位置为(0,0)。 * * Copyright: Copyright (c) * Company: DiaoxianSoft development team * @author Geek_Soledad * @creation date 2011-6-21 下午03:46:29 * @version 0.1 */ public class ImageJPanel extends JPanel { private static final long serialVersionUID = 1940032010486975040L; Image image; /** * 创建具有双缓冲和流布局的新 ImageJPanel。 */ public ImageJPanel() { super(); } /** * 创建具有双缓冲和流布局及指定背景图片的新 ImageJPanel。 * * @param image 指定的背景图片 */ public ImageJPanel(Image image) { super(); this.image = image; } /** * 创建具有指定的布局及缓冲策略的新ImageJPanel。 * * @param layout 要使用的LayoutManager * @param isDoubleBuffered boolean 值, true 表示双缓冲,双缓冲使用更多内存 * 空间实现快速、无闪烁的更新 */ public ImageJPanel(LayoutManager layout, boolean isDoubleBuffered) { super(layout, isDoubleBuffered); } /** * 创建具有指定布局管理器的新缓冲 ImageJPanel * * @param layout the LayoutManager to use */ public ImageJPanel(LayoutManager layout) { super(layout, true); } /** * 创建具有 FlowLayout 和指定缓冲策略的新 ImageJPanel。 * 如果 isDoubleBuffered 为 true,则 JPanel 将使用双缓冲。 * * @param isDoubleBuffered boolean 值,true 表示双缓冲, * 双缓冲使用更多内存空间实现快速、无闪烁的更新 */ public ImageJPanel(boolean isDoubleBuffered) { super(new FlowLayout(), isDoubleBuffered); } /** * 返回此组件的背景图片 * * @return image 此组件的背景图片 */ public Image getImage() { return image; } /** * 设置此组件的背景图片 * * @param image Image 对象 */ public void setImage(Image image) { this.image = image; } /* 重写父类的paintComponent方法,绘制背景图片。 * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) */ protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image, 0, 0, null); } }
由于JPanel中本身含有多个构造方法,添加了Image成员变量之后,要写出通用版的ImageJPanel可能需要组合参数写出更多的构造方法,显得很冗余。因此在这里对其仅作为Demo给出,到时自己参照即可。
以上添加背景图片的两种情况,均已收录在我的diaoxianSoft中的easyJFC包中。此包暂未完善,亦未做正规测试,不知其有多大通用性,仅作为我个人的私有包,在自己写代码中使用。
JFC系列将分享一些常见但又让我们这些新手头疼的问题的解决方法,希望大家继续关注,也希望大家一起分享自己的成果。