Java程序实现【文本信息度量和文本自动换行绘制例程】FontMetrics类和FontRenderContext类

  • 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个字无法显示,与预期结果不符。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值