如何将Tkinter文本框内容导出为PDF文件 出现latin-1编码报错
问题描述
实现Tkinter文本框内容导出为PDF功能时,运行代码抛出Unicode编码错误,相关代码与报错信息如下:
功能实现代码
from tkinter import * from tkinter import ttk from tkinter import filedialog from tkinter.filedialog import askopenfile from tkinter.filedialog import * from fpdf import FPDF def export(self): pdf = FPDF() pdf.add_page() pdf.set_font("Arial", size=15) pdf.cell(40, 10, self.agreemanttext.get("1.0", END).strip()) pdf.output(asksaveasfilename(filetypes=[("PDF file", "*.pdf")]), "F") def agreemnttext(self): self.buying_agreementsample_cash ="""text""" self.agreemanttextframe = Frame(self.agreemantpage, width=900, height=900) self.agreemanttextframe.place(x=1, y=40) self.agreemanttext = Text(self.agreemanttextframe, width=124, height=57) self.agreemanttext.pack() self.agreemanttext.tag_configure('tag-center', justify='right') self.agreemanttext.insert('end', self.buying_agreementsample_cash, 'tag-center') self.agreemanttext.config(state='disabled') self.exportbutton=Button(self.agreemantpage,text="export as pdf",command=self.export) self.exportbutton.place(x=80,y=600)
报错信息
p = self.pages[n].encode("latin1") if PY3K else self.pages[n] UnicodeEncodeError: 'latin-1' codec can't encode characters in position 50-54: ordinal not in range(256)
故障原因
- 旧版
fpdf库默认使用latin-1(ISO-8859-1)编码,仅支持编码值在0-255区间的西欧拉丁字符,无法识别中文、特殊符号等超出该范围的Unicode字符 - 代码中调用的内置
Arial字体没有嵌入对应非拉丁字符的字形,遇到超出编码范围的字符时直接抛出编码错误 - 代码使用
cell()方法渲染文本,该方法不支持自动换行,长文本会直接溢出页面边界
修复步骤
- 卸载旧版fpdf,安装支持Unicode的维护分支fpdf2,API完全兼容原有代码:
pip uninstall fpdf -y pip install fpdf2 - 准备支持目标文本字符集的TTF格式字体文件(比如导出中文可使用思源黑体、系统自带的宋体/微软雅黑等)
- 修改导出函数逻辑:加载自定义字体、替换
cell()为支持自动换行的multi_cell()、增加保存路径非空判断避免用户取消时报错,修改后的参考代码:def export(self): pdf = FPDF() pdf.add_page() # 加载本地TTF字体,参数依次为:自定义字体名、字体样式、字体文件本地路径 pdf.add_font("CustomFont", "", "msyh.ttc") # 此处以微软雅黑字体为例,可替换为自己的字体文件路径 pdf.set_font("CustomFont", size=15) # 获取文本框内容 content = self.agreemanttext.get("1.0", END).strip() # multi_cell第一个参数设为0表示占满页面可用宽度,自动换行 pdf.multi_cell(0, 10, content) save_path = asksaveasfilename(defaultextension=".pdf", filetypes=[("PDF file", "*.pdf")]) # 用户点击取消时save_path为空,不执行保存避免报错 if save_path: pdf.output(save_path, "F")
注意:不要依赖fpdf内置的Helvetica、Arial等字体,这类字体均为latin-1编码的西文字体,无法渲染中文等非拉丁字符,必须手动加载支持对应语言的TTF字体文件。
内容的提问来源于stack exchange,提问作者asaad kittaneh
相关产品推荐
相关产品推荐

