问题引出
我们在程序打印输出时,如何我们所输出的字符中包含emoji文本,或者其它特殊的字符文本,则我们的打印对齐效果将出现错位。以下代码复现了这一效果(tips: 马老师 前面的 | 符号是为了观察对齐效果):
# -*- coding:UTF-8 -*-
# region 引入必要依赖
from DebugInfo.DebugInfo import *
# endregion
if __name__ == "__main__":
画板 = 打印模板()
画板.打印空行(2)
画板.准备表格()
画板.添加一行('序号', '姓名', '自评', '班主任').修饰行(青字) # 作为标题行
画板.添加一行('1', '小红', '我很开朗', '|马老师')
画板.添加分隔行()
画板.添加一行('2', '猪小明', '我得了很多小花 ❌', '|马老师')
画板.添加分隔行()
画板.添加一行('3', '赵虹', '我有爱心♥', '|马老师')
画板.添加分隔行()
画板.添加一行('4', '张天志', '我是女生♀️我有长头发', '|马老师')
画板.添加空行()
画板.展示表格()
👆以上代码的运行打印对齐如下:
我们可以观察到,猪小明行,马老师靠前了
我们又可以观察到,张天志行,马老师靠后了
原因解释
为什么会出现上面的对齐的现象呢?这就要从字体说起了。
我们电脑上,所显示的符号肯定是通过某一个字体来显示的。所以同一个字,我们在宋体下看到的效果,和在黑体下看到的效果,是不一样的。
一个字符,显示其效果所占用的屏幕像素数量,称为字符的显示像素宽度;为方便其见,我们将字符的像素宽度相对于英文字符空格所占用的像素宽度的比值,做为下文我们要描述的字符显示宽度值。
- 显然,英文空格的字符显示宽度值是 1
- 一个英文字符(大写和小写)的显示宽度值是 1
- 对于以下显示的楷体字体下的中文,一个字符的显示宽度值是 2
显示,对于任何可以在电脑上显示的字符,其都有一个显示宽度,只是不同的字符,在不同的字体下,其显示宽度值不同罢了。
有了以上规律后,我们如果需要对齐文本,就会比较容易了。我们计算字符的显示宽度,根据其显示宽度,计算并补充对应数量的空格后,文本就可以达到对齐的效果。
那现在来说上面马老师对不齐的问题。根据上文中的对齐原理的解释,马老师对不齐,肯定是文本中存在了这样的字符,这字符计算的显示宽度,与其实际显示所占用的宽度不一致,导致在补充空格时空格数量计算错误。
找出真凶
在上面的表格中,我们发现符号 ❌ ♥ ♀️ 是不常的字符。我们把这几个字符拿掉,再来观察对齐效果,如下👇:
# -*- coding:UTF-8 -*-
# region 引入必要依赖
from DebugInfo.DebugInfo import *
# endregion
if __name__ == "__main__":
画板 = 打印模板()
画板.打印空行(2)
画板.准备表格()
画板.添加一行('序号', '姓名', '自评', '班主任').修饰行(青字) # 作为标题行
画板.添加一行('1', '小红', '我很开朗', '|马老师')
画板.添加分隔行()
# 画板.添加一行('2', '猪小明', '我得了很多小花 ❌', '|马老师')
画板.添加一行('2', '猪小明', '我得了很多小花 ', '|马老师')
画板.添加分隔行()
# 画板.添加一行('3', '赵虹', '我有爱心♥', '|马老师')
画板.添加一行('3', '赵虹', '我有爱心', '|马老师')
画板.添加分隔行()
# 画板.添加一行('4', '张天志', '我是女生♀️我有长头发', '|马老师')
画板.添加一行('4', '张天志', '我是女生我有长头发', '|马老师')
画板.添加空行()
画板.展示表格()
👆以上代码运行效果如下👇:
嗯,对齐效果非常漂亮。
所以,我们将问题的焦点放在符号 ❌ ❤ ♀️ 这三个字符上。 以下代码打印并显示了这三个字符的显示宽度和实际占用宽度。
# -*- coding:UTF-8 -*-
# region 引入必要依赖
from DebugInfo.DebugInfo import *
# endregion
if __name__ == "__main__":
画板 = 打印模板()
画板.打印空行(2)
画板.准备表格()
画板.添加一行('字符','显示宽度值').修饰行(青字)
画板.添加分隔行()
画板.添加一行('❌|',显示宽度('❌'))
画板.添加一行('♥|',显示宽度('♥'))
画板.添加一行('♀️|',显示宽度('♀️'))
画板.添加空行()
画板.展示表格()
👆以上代码运行效果如下👇:
上图我们可以看到(注意看参考符号 | 的位置):
- 字符 ❌ 显示占用宽度为1, 计算的显示宽度是2 (这将导致在对齐补空格时,少补一个空格)
- 字符 ♥ 显示占用宽度为1,计算的显示宽度也是1 (实际显示宽度和计算显示宽度一致,对齐补齐空格正常)
- 字符 ♀️ 显示占用宽度为2,但计算的显示宽度为1 (这将导致在对齐补空格时,多补一个空格)
所以,对齐出错的根本原因在于符号 ♥ 和 ♀️ 在终端显示时,显示这两个字符所占用的字符宽度与计算的字符宽度不一致,导致在计算对齐补空格时,补了错误数量的空格。
补救措施
有了以上的分析,我们知道了出现对齐错位的根本原因在于部分特殊的字符显示宽度值的计算与实际不符导致,那么我们对应的解决方案也就明朗了:修正特殊字符的显示宽度值
如下的代码,我们指定了特殊字符的显示宽度值,并将其告诉了【打印模板对象】(这里是画板),然后我们又打印显示了带有特殊字符的文本,观察其对齐效果:
# -*- coding:UTF-8 -*-
# region 引入必要依赖
from DebugInfo.DebugInfo import *
# endregion
if __name__ == "__main__":
画板 = 打印模板()
画板.打印空行(2)
画板.准备表格()
画板.设置特殊字符宽度字典({'❌': 1, '♀': 2}) # 修正特殊符号的显示宽度值
画板.添加一行('序号', '姓名', '自评', '班主任').修饰行(青字) # 作为标题行
画板.添加一行('1', '小红', '我很开朗', '|马老师')
画板.添加一行('2', '猪小明', '我得了很多小花❌', '|马老师')
画板.添加一行('3', '赵虹', '我有爱心♥', '|马老师')
画板.添加一行('4', '张天志', '我是女生♀️我有长头发', '|马老师')
画板.添加空行()
画板.展示表格()
👆上面的代码中,请留意 设置特殊字符宽度字典 方法,其修正了符号 ❌和 ♀️ 的显示宽度值,这帮助程序正确的理解和计算了字符的实际显示宽度,从而在对齐补齐空格时,可以补齐正确数量的空格。
其它的坑
在以上的分析过程中,我们所提到,所有在电脑上显示处理的符号,都依赖于字体,这也就是说,在不同的字体下,同一个符号可能显示的宽度(相对于空格或者符号 -),是有可能不同的,现观察到的部分字体中,英文字符的宽度如果计算为单位1,中文字符的宽度是1.5,在这种非整数倍的字体下,遇到中英文混合情况时,对齐处理是非常难的,甚至是无法做到的。
对于特殊字符,同样在不同的字体下,其显示宽度也是不同的,在实际的应用中要多加留意处理。
另外,为了方便文本对齐的计算,大家在实际使用时,需要注意终端所使用的字体是否是等宽字体,非等宽字体下,可能出现字体宽度不是整数的情况,对齐处理效果会受到影响。
小结
非常感谢大家的关注和阅读,如果哪里有些的不对的地方,望批评指出,以便及时修正。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。