

Python,速成心法
敲代码,查资料,问Ai
练习,探索,总结,优化

★★★★★博文创作不易,源码代码的过程中,如有疑问的地方,欢迎大家指正留言交流。喜欢的老铁可以多多点赞+收藏分享+置顶,小红牛在此表示感谢。★★★★★
office办公python代码:PDF书籍封面生成器1.0(tk+reportlab)
office办公python代码:批量对所有.pdf文件生成水印(pypdf+reportlab)

↓ 完整源码如下 ↓
# -*- coding: utf-8 -*-# @Author : 小红牛# 微信公众号:wdPythonimport tkinter as tkfrom tkinter import scrolledtext, filedialog, ttk, messageboxfrom reportlab.lib.pagesizes import A4from reportlab.pdfbase import pdfmetricsfrom reportlab.pdfbase.ttfonts import TTFontfrom reportlab.lib.styles import getSampleStyleSheetfrom reportlab.lib.units import inchfrom reportlab.platypus import SimpleDocTemplate, Paragraph, Spacerimport osfrom xml.sax.saxutils import escapeclass PDFGeneratorApp:# 字体映射(Windows 系统字体路径)FONT_MAP = {"楷体": r"C:\Windows\Fonts\simkai.ttf","微软雅黑": r"C:\Windows\Fonts\msyh.ttf","黑体": r"C:\Windows\Fonts\simhei.ttf","华文宋体": r"C:\Windows\Fonts\STSONG.TTF","华文楷体": r"C:\Windows\Fonts\STKAITI.TTF","华文仿宋": r"C:\Windows\Fonts\STFANGSO.TTF","华文细黑": r"C:\Windows\Fonts\STXIHEI.TTF",}DEFAULT_FONT = "楷体"DEFAULT_SIZE = 12DEFAULT_FILENAME = "output.pdf"DEFAULT_MARGIN = 36 # 统一页边距(磅)DEFAULT_LINE_SPACING = 2 # 额外行距(磅)def __init__(self, root):self.root = rootself.root.title("文本转 PDF 工具")self.root.geometry("750x550")# ---------- 参数分组(ttk.LabelFrame) ----------param_frame = ttk.LabelFrame(root, text="PDF参数设置", padding=10)param_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=5)# ---- 第一行:字体、字号、文件名 ----row1 = tk.Frame(param_frame)row1.pack(side=tk.TOP, fill=tk.X, pady=2)# 字体font_group = tk.Frame(row1)font_group.pack(side=tk.LEFT, padx=5)tk.Label(font_group, text="字体:").pack(side=tk.LEFT)self.font_var = tk.StringVar(value=self.DEFAULT_FONT)font_combo = ttk.Combobox(font_group, textvariable=self.font_var,values=list(self.FONT_MAP.keys()), state="readonly", width=12)font_combo.pack(side=tk.LEFT)# 字号size_group = tk.Frame(row1)size_group.pack(side=tk.LEFT, padx=5)tk.Label(size_group, text="字号:").pack(side=tk.LEFT)preset_sizes = [10, 12, 14, 16, 18, 20, 24]self.size_var = tk.StringVar(value=str(self.DEFAULT_SIZE))size_combo = ttk.Combobox(size_group, textvariable=self.size_var,values=preset_sizes, state="normal", width=6)size_combo.pack(side=tk.LEFT)# 文件名filename_group = tk.Frame(row1)filename_group.pack(side=tk.LEFT, padx=5)tk.Label(filename_group, text="文件名:").pack(side=tk.LEFT)self.filename_var = tk.StringVar(value=self.DEFAULT_FILENAME)filename_entry = tk.Entry(filename_group, textvariable=self.filename_var, width=20)filename_entry.pack(side=tk.LEFT)tk.Label(row1, text="页边距:").pack(side=tk.LEFT)self.margin_var = tk.StringVar(value=str(self.DEFAULT_MARGIN))margin_entry = tk.Entry(row1, textvariable=self.margin_var, width=8)margin_entry.pack(side=tk.LEFT)# 额外行距tk.Label(row1, text="行距:").pack(side=tk.LEFT)self.spacing_var = tk.StringVar(value=str(self.DEFAULT_LINE_SPACING))spacing_entry = tk.Entry(row1, textvariable=self.spacing_var, width=8)spacing_entry.pack(side=tk.LEFT)# ---- 按钮行(仍在 LabelFrame 内,或独立放置,这里放在 LabelFrame 内更统一) ----row2 = tk.Frame(param_frame)row2.pack(side=tk.TOP, fill=tk.X, pady=5)import_btn = tk.Button(row2, text="从txt文件导入文本", command=self.import_text, width=18)import_btn.pack(side=tk.LEFT, padx=5)generate_btn = tk.Button(row2, text="生成 PDF", command=self.generate_pdf, width=15)generate_btn.pack(side=tk.LEFT, padx=5)# ---------- 主文本框 ----------self.text_area = scrolledtext.ScrolledText(root, wrap=tk.WORD, font=("楷体", 12), height=20)self.text_area.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)def import_text(self):"""从 txt 文件导入文本,并自动填充文件名"""file_path = filedialog.askopenfilename(filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")])if not file_path:returntry:with open(file_path, "r", encoding="utf-8") as f:content = f.read()self.text_area.delete("1.0", tk.END)self.text_area.insert("1.0", content)# 自动填充文件名base = os.path.basename(file_path)name, ext = os.path.splitext(base)new_filename = name + ".pdf"self.filename_var.set(new_filename)messagebox.showinfo("导入成功", f"已导入文件:{base}")except Exception as e:messagebox.showerror("导入失败", str(e))def generate_pdf(self):"""生成 PDF(使用弹窗提示)"""text = self.text_area.get("1.0", tk.END).strip()if not text:messagebox.showwarning("提示", "文本内容为空,请先输入或导入文本")return# 获取参数font_name = self.font_var.get()try:font_size = float(self.size_var.get())if font_size <= 0:raise ValueErrorexcept ValueError:messagebox.showerror("错误", "字号必须为正数")returnfilename = self.filename_var.get().strip()if not filename:filename = self.DEFAULT_FILENAMEif not filename.lower().endswith(".pdf"):filename += ".pdf"# 读取统一页边距try:margin = float(self.margin_var.get())if margin <= 0:raise ValueError("页边距必须为正数")except ValueError:messagebox.showerror("错误", "页边距必须为正数")return# 读取额外行距try:extra_spacing = float(self.spacing_var.get())if extra_spacing < 0:raise ValueError("行距不能为负")except ValueError:messagebox.showerror("错误", "行距必须为大于等于0的数")return# 获取字体路径font_path = self.FONT_MAP.get(font_name)if not font_path or not os.path.exists(font_path):font_path = self.FONT_MAP.get(self.DEFAULT_FONT)if not font_path or not os.path.exists(font_path):pdf_font_name = "Helvetica"messagebox.showwarning("字体警告", "未找到中文字体,将使用英文字体(中文可能显示为方框)")else:pdf_font_name = "ChineseFont"else:pdf_font_name = "ChineseFont"# 注册中文字体if pdf_font_name == "ChineseFont":try:pdfmetrics.registerFont(TTFont('ChineseFont', font_path))except Exception as e:messagebox.showwarning("字体警告", f"字体注册失败:{e},将使用英文字体")pdf_font_name = "Helvetica"# ---------- 生成 PDF ----------try:doc = SimpleDocTemplate(filename,pagesize=A4,leftMargin=margin,rightMargin=margin,topMargin=margin,bottomMargin=margin,)styles = getSampleStyleSheet()style = styles['Normal']style.fontName = pdf_font_namestyle.fontSize = font_sizelines = text.split('\n')story = []for line in lines:if line.strip() == '':story.append(Spacer(1, 0.2 * inch)) # 空行占位else:safe_line = escape(line)story.append(Paragraph(safe_line, style))if extra_spacing > 0:story.append(Spacer(1, extra_spacing))doc.build(story)messagebox.showinfo("成功", f"PDF 已生成:\n{filename}")except Exception as e:messagebox.showerror("生成失败", str(e))if __name__ == "__main__":root = tk.Tk()app = PDFGeneratorApp(root)root.mainloop()
完毕!!感谢您的收看
------★★历史博文集合★★------
