当前位置: 首页 > news >正文

emoji对齐 特殊字符对齐 文本对齐

emoji如何对齐 特殊字符如何对齐 高级文本对齐

问题引出

我们在程序打印输出时,如何我们所输出的字符中包含emoji文本,或者其它特殊的字符文本,则我们的打印对齐效果将出现错位。以下代码复现了这一效果(tips: 马老师 前面的 | 符号是为了观察对齐效果):

# -*- coding:UTF-8 -*-# region 引入必要依赖
from DebugInfo.DebugInfo import *# endregionif __name__ == "__main__":画板 = 打印模板()画板.打印空行(2)画板.准备表格()画板.添加一行('序号', '姓名', '自评', '班主任').修饰行(青字)  # 作为标题行画板.添加一行('1', '小红', '我很开朗', '|马老师')画板.添加分隔行()画板.添加一行('2', '猪小明', '我得了很多小花 ❌', '|马老师')画板.添加分隔行()画板.添加一行('3', '赵虹', '我有爱心♥', '|马老师')画板.添加分隔行()画板.添加一行('4', '张天志', '我是女生♀️我有长头发', '|马老师')画板.添加空行()画板.展示表格()

👆以上代码的运行打印对齐如下:

20231104175834

我们可以观察到,猪小明行,马老师靠前了
我们又可以观察到,张天志行,马老师靠后了

原因解释

为什么会出现上面的对齐的现象呢?这就要从字体说起了。
我们电脑上,所显示的符号肯定是通过某一个字体来显示的。所以同一个字,我们在宋体下看到的效果,和在黑体下看到的效果,是不一样的。

一个字符,显示其效果所占用的屏幕像素数量,称为字符的显示像素宽度;为方便其见,我们将字符的像素宽度相对于英文字符空格所占用的像素宽度的比值,做为下文我们要描述的字符显示宽度值。

  • 显然,英文空格的字符显示宽度值是 1
  • 一个英文字符(大写和小写)的显示宽度值是 1
  • 对于以下显示的楷体字体下的中文,一个字符的显示宽度值是 2
    20231104181232

显示,对于任何可以在电脑上显示的字符,其都有一个显示宽度,只是不同的字符,在不同的字体下,其显示宽度值不同罢了。

有了以上规律后,我们如果需要对齐文本,就会比较容易了。我们计算字符的显示宽度,根据其显示宽度,计算并补充对应数量的空格后,文本就可以达到对齐的效果。

那现在来说上面马老师对不齐的问题。根据上文中的对齐原理的解释,马老师对不齐,肯定是文本中存在了这样的字符,这字符计算的显示宽度,与其实际显示所占用的宽度不一致,导致在补充空格时空格数量计算错误。

找出真凶

在上面的表格中,我们发现符号 ❌ ♥ ♀️ 是不常的字符。我们把这几个字符拿掉,再来观察对齐效果,如下👇:

# -*- coding:UTF-8 -*-# region 引入必要依赖
from DebugInfo.DebugInfo import *# endregionif __name__ == "__main__":画板 = 打印模板()画板.打印空行(2)画板.准备表格()画板.添加一行('序号', '姓名', '自评', '班主任').修饰行(青字)  # 作为标题行画板.添加一行('1', '小红', '我很开朗', '|马老师')画板.添加分隔行()# 画板.添加一行('2', '猪小明', '我得了很多小花 ❌', '|马老师')画板.添加一行('2', '猪小明', '我得了很多小花 ', '|马老师')画板.添加分隔行()# 画板.添加一行('3', '赵虹', '我有爱心♥', '|马老师')画板.添加一行('3', '赵虹', '我有爱心', '|马老师')画板.添加分隔行()# 画板.添加一行('4', '张天志', '我是女生♀️我有长头发', '|马老师')画板.添加一行('4', '张天志', '我是女生我有长头发', '|马老师')画板.添加空行()画板.展示表格()

👆以上代码运行效果如下👇:

20231104222547

嗯,对齐效果非常漂亮。
所以,我们将问题的焦点放在符号 ❌ ❤ ♀️ 这三个字符上。 以下代码打印并显示了这三个字符的显示宽度和实际占用宽度。

# -*- coding:UTF-8 -*-# region 引入必要依赖
from DebugInfo.DebugInfo import *# endregionif __name__ == "__main__":画板 = 打印模板()画板.打印空行(2)画板.准备表格()画板.添加一行('字符','显示宽度值').修饰行(青字)画板.添加分隔行()画板.添加一行('❌|',显示宽度('❌'))画板.添加一行('♥|',显示宽度('♥'))画板.添加一行('♀️|',显示宽度('♀️'))画板.添加空行()画板.展示表格()

👆以上代码运行效果如下👇:
20231104213053
上图我们可以看到(注意看参考符号 | 的位置):

  • 字符 ❌ 显示占用宽度为1, 计算的显示宽度是2 (这将导致在对齐补空格时,少补一个空格)
  • 字符 ♥ 显示占用宽度为1,计算的显示宽度也是1 (实际显示宽度和计算显示宽度一致,对齐补齐空格正常)
  • 字符 ♀️ 显示占用宽度为2,但计算的显示宽度为1 (这将导致在对齐补空格时,多补一个空格)

所以,对齐出错的根本原因在于符号 ♥ 和 ♀️ 在终端显示时,显示这两个字符所占用的字符宽度与计算的字符宽度不一致,导致在计算对齐补空格时,补了错误数量的空格。

补救措施

有了以上的分析,我们知道了出现对齐错位的根本原因在于部分特殊的字符显示宽度值的计算与实际不符导致,那么我们对应的解决方案也就明朗了:修正特殊字符的显示宽度值

如下的代码,我们指定了特殊字符的显示宽度值,并将其告诉了【打印模板对象】(这里是画板),然后我们又打印显示了带有特殊字符的文本,观察其对齐效果:

# -*- coding:UTF-8 -*-# region 引入必要依赖
from DebugInfo.DebugInfo import *# endregionif __name__ == "__main__":画板 = 打印模板()画板.打印空行(2)画板.准备表格()画板.设置特殊字符宽度字典({'❌': 1, '♀': 2})  # 修正特殊符号的显示宽度值画板.添加一行('序号', '姓名', '自评', '班主任').修饰行(青字)  # 作为标题行画板.添加一行('1', '小红', '我很开朗', '|马老师')画板.添加一行('2', '猪小明', '我得了很多小花❌', '|马老师')画板.添加一行('3', '赵虹', '我有爱心♥', '|马老师')画板.添加一行('4', '张天志', '我是女生♀️我有长头发', '|马老师')画板.添加空行()画板.展示表格()

👆上面的代码中,请留意 设置特殊字符宽度字典 方法,其修正了符号 ❌和 ♀️ 的显示宽度值,这帮助程序正确的理解和计算了字符的实际显示宽度,从而在对齐补齐空格时,可以补齐正确数量的空格。

20231104222101

其它的坑

在以上的分析过程中,我们所提到,所有在电脑上显示处理的符号,都依赖于字体,这也就是说,在不同的字体下,同一个符号可能显示的宽度(相对于空格或者符号 -),是有可能不同的,现观察到的部分字体中,英文字符的宽度如果计算为单位1,中文字符的宽度是1.5,在这种非整数倍的字体下,遇到中英文混合情况时,对齐处理是非常难的,甚至是无法做到的。

对于特殊字符,同样在不同的字体下,其显示宽度也是不同的,在实际的应用中要多加留意处理。

另外,为了方便文本对齐的计算,大家在实际使用时,需要注意终端所使用的字体是否是等宽字体,非等宽字体下,可能出现字体宽度不是整数的情况,对齐处理效果会受到影响。

小结

非常感谢大家的关注和阅读,如果哪里有些的不对的地方,望批评指出,以便及时修正。

对于特殊字符,同样在不同的字体下,其显示宽度也是不同的,在实际的应用中要多加留意处理。

另外,为了方便文本对齐的计算,大家在实际使用时,需要注意终端所使用的字体是否是等宽字体,非等宽字体下,可能出现字体宽度不是整数的情况,对齐处理效果会受到影响。

小结

非常感谢大家的关注和阅读,如果哪里有些的不对的地方,望批评指出,以便及时修正。

相关文章:

  • webSocket推送太快导致前端渲染卡顿问题优化
  • Ubuntu上安装 Chrome 浏览器
  • Object转List<>,转List<Map<>>
  • 一分钟理解npm run dev 和 npm run serve
  • 时序分解 | Matlab实现EEMD集合经验模态分解时间序列信号分解
  • 整理的一些Java细节问题
  • 轻量封装WebGPU渲染系统示例<14>- 多线程模型载入(源码)
  • linux环境下编译,安卓平台使用的luajit库
  • 七、W5100S/W5500+RP2040树莓派Pico<UDP 组播>
  • VSCode中的任务什么情况下需要配置多个问题匹配器problemMatcher?多个问题匹配器之间的关系是什么?
  • rust入门基础案例:猜数字游戏
  • Qt for Android代码中输出日志
  • Kubernetes群集调度
  • 基于ASP.NET MVC + Bootstrap的仓库管理系统
  • Ubuntu20.04下安装Redis环境
  • [译]如何构建服务器端web组件,为何要构建?
  • 《剑指offer》分解让复杂问题更简单
  • 【Amaple教程】5. 插件
  • 2018一半小结一波
  • 30天自制操作系统-2
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • crontab执行失败的多种原因
  • JavaScript 奇技淫巧
  • JS笔记四:作用域、变量(函数)提升
  • python 装饰器(一)
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • SSH 免密登录
  • vue自定义指令实现v-tap插件
  • yii2权限控制rbac之rule详细讲解
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 关于springcloud Gateway中的限流
  • 今年的LC3大会没了?
  • 开发基于以太坊智能合约的DApp
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 设计模式 开闭原则
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • ​2020 年大前端技术趋势解读
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • #Linux(帮助手册)
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (1) caustics\
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (2)MFC+openGL单文档框架glFrame
  • (done) 两个矩阵 “相似” 是什么意思?
  • (二)hibernate配置管理
  • (力扣题库)跳跃游戏II(c++)
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (五)Python 垃圾回收机制
  • (一)Neo4j下载安装以及初次使用
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .Net MVC4 上传大文件,并保存表单