- Java程序实现文本信息度量和文本自动换行绘制例程,在有些场景文本信息的绘制需要自行控制换行,这里就需要对文本信息进行度量,然后才能进行准确绘制。
这种情形需要用到FontMetrics类和FontRenderContext类。下面是一个应用实例:
package image.AffineTransform;
/***
* @author QiuGen
* @description 文本的度量绘制例程TextMetrics
* 实现功能:文本的度量,自动换行绘制。
* @date 2024/04/19
* ***/
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.*;
import javax.swing.*;
public class TextMetrics extends JComponent {
private static final int DEFAULT_WIDTH = 600;
private static final int DEFAULT_HEIGHT = 140;
private String message;
private Font font;
public TextMetrics(String text, Font font) {
message = text;
this.font = font;
setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
// 抗锯齿 添加文字
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setFont(font);
Color color = Color.BLUE;
g2d.setColor(color);
// 换行算法:文本信息按指定行宽,自动换行
customDrawText(g2d, font, message, 40, 10, getWidth()-30);
g2d.dispose();
}
/***定制文本信息显示,按指定行宽,自动换行***/
public void customDrawText(Graphics2D g2D, Font font, String text, int x, int y, int width) {
FontMetrics metrics = g2D.getFontMetrics(font);
int height = metrics.getHeight(); // 获取文本显示高度
//度量文本信息的大小。FontRenderContext是字体渲染器对象
FontRenderContext context=g2D.getFontRenderContext();
//获取文本信息所占空间的范围
Rectangle2D bnds=font.getStringBounds(message, context);
int ascent = (int)-bnds.getY(); //计算上坡度(ascent)
//int baseY = y + (int)ascent; //基线的y坐标
int w = 0; //记录每行文本信息宽度
int count = 0;
int len = text.length();
String subText = text;
String line="";
int lineNo = 0; //行号,从0开始。
for (int i = 0; i < len; i++) {
// 统计字符串宽度 并与 预设好的宽度 作比较
if (w <= width-metrics.charWidth(text.charAt(0))) {
w += metrics.charWidth(text.charAt(i)); // 获取每个字符的宽度
count++;
} else { //逐行绘制文本信息
line = subText.substring(0, count);
g2D.drawString(line, x, y+(lineNo * height)+ ascent); //+ ascent; //基线的y坐标
subText = subText.substring(count);
lineNo++;
w = metrics.charWidth(text.charAt(i)); //重置
count = 1; //重置
}
if (i == len-1) { // 最后一行特别处理
line = subText.substring(0, count);
g2D.drawString(line, x, y + (lineNo * height)+ ascent);
}
}
}
public static void main(String[] args) {
String text = "春城万户瓮醪香,闻道明州是醉乡。莫怪儿童笑山简,明州风物胜襄阳。——《明州歌选》明 李濂";
JFrame frame = new JFrame("文本的度量绘制测试");
Font font = new Font("华文彩云", Font.BOLD, 32);
frame.add(new TextMetrics(text,font));
frame.pack(); //按组件的首选大小显示
frame.setVisible(true);
}
}
例程的运行效果图如下所示:
参考文献博客:
《java制作海报一:java使用Graphics2D 在图片上写字,文字换行算法详解》
- 学习此文献深受教益,本博客的换行算法汲取了该博客的精华。
但该博客的换行算法略有瑕疵,换行算法方法drawWordAndLineFeed()有一个小BUG。请博主允许我来分析一下此方法,下面是这个方法的源代码:
/**
* @return void
* @Author fengfanli
* @Description //TODO 写字换行算法
* @Date 18:08 2021/4/1
* @Param []
**/
private static void drawWordAndLineFeed(Graphics2D g2d, Font font, String words, int wordsX, int wordsY, int wordsWidth) {
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
// 获取字符的最高的高度
int height = metrics.getHeight();
int width = 0;
int count = 0;
int total = words.length();
String subWords = words;
int b = 0;
for (int i = 0; i < total; i++) {
// 统计字符串宽度 并与 预设好的宽度 作比较
if (width <= wordsWidth) {
width += metrics.charWidth(words.charAt(i)); // 获取每个字符的宽度
count++;
} else {
// 画 除了最后一行的前几行
String substring = subWords.substring(0, count);
g2d.drawString(substring, wordsX, wordsY + (b * height));
subWords = subWords.substring(count);
b++;
width = 0;
count = 0;
}
// 画 最后一行字符串
if (i == total - 1) {
g2d.drawString(subWords, wordsX, wordsY + (b * height));
}
}
}
其中的else语句块中以下这二行(重置赋值)代码不正确:
width = 0;
count = 0;
这二行代码用下面二行代码替换,即可修正这个小BUG:
width = metrics.charWidth(text.charAt(i)); //重置
count = 1; //重置
- 如果不更新这二行,文本信息的尾部将无法显示。假如文本信息较长,要分成n行显示,最后n-1个字无法显示,与预期结果不符。