《Swing Hacks》中说:Swing的各种特性中最没有被充分利用的就是其部分重写绘图代码的能力,在改善窗口外观时,大部分程序要么使用渲染器,要么就完全重绘代码,其实通过部分重写绘图代码,就能创建很有用的绘图效果。实际代码如下,部分注释解释了其原理:
package com.qing;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.TexturePaint;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class WatermarkTextField extends JTextField {
private static final long serialVersionUID = 1L;
public static final Image LOG = new ImageIcon(
WatermarkTextField.class.getResource("/resource/images/LOG.png"))
.getImage();
private BufferedImage img;
private TexturePaint texture;
/**
* 构造函数通过传递一张图作为其背景图
*
* @param file:图像文件
* @throws IOException
*/
public WatermarkTextField(File file) throws IOException {
// 通过文件的方式获取BufferedImage
img = ImageIO.read(file);
// 根据指定图像的大小创建一个基准矩形,此矩形和图像大小相等(如果想矩形小一点,,也可绘制部分)
Rectangle rect = new Rectangle(0, 0, img.getWidth(null),
img.getHeight(null));
/** TexturePaint 类提供一种用于被指定为 BufferedImage 的纹理填充 Shape 的方式 **/
texture = new TexturePaint(img, rect);
// 使此文本框透明
setOpaque(false);
}
@Override
public void paintComponent(Graphics g) {
/** 在调用父类的绘图方法前绘制好背景 **/
Graphics2D g2 = (Graphics2D) g;
// 为 Graphics2D 设置 TexturePaint 属性
g2.setPaint(texture);
// 获取文本框的的大小,并将其全部填充
g.fillRect(0, 0, getWidth(), getHeight());
// 然后重用父类的绘图方法,比如绘制文本字符信息等
super.paintComponent(g);
}
//到此已经完成文本框背景图的重绘,下面进行测试
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame("Swing Hacks 005:添加背景的文本框");
frame.setIconImage(LOG);
JTextField textfield = new WatermarkTextField(new File(
WatermarkTextField.class
.getResource("/resource/images/red.png").toURI()));
textfield.setText(" Thia ia a TextField ");
textfield.setFont(textfield.getFont().deriveFont(50f));//设置文本字体
frame.getContentPane().add(textfield, BorderLayout.NORTH);
frame.pack();
frame.setVisible(true);
}
}
效果如下: