基本功能:
实时拼音标注
- 即时响应:输入中文时自动实时生成拼音
- 多行支持:支持长文本输入,自动显示滚动条
- 智能处理:自动过滤非汉字字符的拼音显示
- ✅ 支持字符类型:
- 简体中文
- 繁体中文
- 中文标点(自动过滤)
- 数字/字母(保留显示,无拼音)
- ❌ 排除字符:
- 空格/制表符
- 常见标点:,。!?、()【】「」《》
- 特殊符号:@#¥%……&*
导出图片功能:
- 自动包含拼音和汉字的排版效果- 保存当前显示内容为PNG格式
- 支持滚动区域当前视图的截图
复制拼音功能:
- 用空格连接有效拼音
- 直接存入系统剪贴板
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
from pypinyin import pinyin, Style
class PinyinAnnotator:
def __init__(self, root):
self.root = root
self.root.title("中文拼音标注工具")
self.root.geometry("800x600")
# 创建界面组件
self.create_widgets()
# 配置样式
self.configure_styles()
def create_widgets(self):
"""创建界面组件"""
main_frame = ttk.Frame(self.root)
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# 输入区域
input_frame = ttk.LabelFrame(main_frame, text="输入中文")
input_frame.pack(fill=tk.X, pady=5)
self.input_text = scrolledtext.ScrolledText(
input_frame,
height=8,
font=('微软雅黑', 14),
wrap=tk.WORD
)
self.input_text.pack(fill=tk.BOTH, expand=True)
self.input_text.bind('<KeyRelease>', self.update_pinyin)
# 显示区域
display_frame = ttk.LabelFrame(main_frame, text="带拼音显示")
display_frame.pack(fill=tk.BOTH, expand=True, pady=5)
self.display_canvas = tk.Canvas(
display_frame,
bg='white'
)
scrollbar = ttk.Scrollbar(
display_frame,
orient="vertical",
command=self.display_canvas.yview
)
self.display_canvas.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.display_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# 状态栏
self.status_var = tk.StringVar()
status_bar = ttk.Label(
main_frame,
textvariable=self.status_var,
relief=tk.SUNKEN
)
status_bar.pack(fill=tk.X)
# 在原控制面板代码后添加新按钮
control_frame = ttk.Frame(main_frame)
control_frame.pack(fill=tk.X, pady=5)
ttk.Button(control_frame, text="导出图片", command=self.export_image,
style='TButton').pack(side=tk.LEFT, padx=5)
ttk.Button(control_frame, text="复制拼音", command=self.copy_pinyin,
style='TButton').pack(side=tk.LEFT, padx=5)
def configure_styles(self):
"""配置界面样式"""
style = ttk.Style()
style.configure('TLabel', font=('微软雅黑', 10))
style.configure('TButton', font=('微软雅黑', 10))
style.configure('TLabelFrame', font=('微软雅黑', 11, 'bold'))
style.configure('StatusBar.TLabel', font=('微软雅黑', 9))
def get_pinyin(self, text):
"""获取带声调的拼音(过滤标点)"""
try:
# 添加自定义处理逻辑
pinyin_list = []
for char in text:
if char.strip() and not self.is_punctuation(char):
# 处理汉字
py = pinyin(char, style=Style.TONE, errors='ignore')[0][0]
pinyin_list.append(py)
else:
# 非汉字字符返回空字符串
pinyin_list.append('')
return pinyin_list
except Exception as e:
self.status_var.set(f"错误: {str(e)}")
return []
def is_punctuation(self, char):
"""判断是否为标点符号"""
# Unicode标点符号范围
cp = ord(char)
return (cp >= 0x2000 and cp <= 0x206F) or \
(cp >= 0x3000 and cp <= 0x303F) or \
(cp >= 0xFF00 and cp <= 0xFFEF)
def calculate_layout(self, text, pinyins):
"""计算文本布局"""
char_width = 30 # 每个字符的显示宽度
line_height = 60 # 每行高度
x_start = 20 # 起始X坐标
y_start = 20 # 起始Y坐标
layout = []
current_x = x_start
current_y = y_start
for char, py in zip(text, pinyins):
# 换行处理
if current_x + char_width > 780: # 考虑滚动条宽度
current_x = x_start
current_y += line_height
layout.append({
'char': char,
'pinyin': py,
'x': current_x,
'y': current_y
})
current_x += char_width
return layout, current_y + line_height
def update_pinyin(self, event=None):
"""更新拼音显示"""
# 获取输入文本
text = self.input_text.get("1.0", tk.END).strip()
if not text:
self.display_canvas.delete("all")
self.status_var.set("就绪")
return
# 生成拼音
pinyins = self.get_pinyin(text)
# 计算布局
self.display_canvas.delete("all")
layout, total_height = self.calculate_layout(text, pinyins)
# 绘制拼音和汉字
for item in layout:
# 绘制拼音
self.display_canvas.create_text(
item['x'] + 15,
item['y'],
text=item['pinyin'],
fill='#666',
font=('微软雅黑', 10),
anchor='s'
)
# 绘制汉字
self.display_canvas.create_text(
item['x'] + 15,
item['y'] + 25,
text=item['char'],
fill='#333',
font=('微软雅黑', 14),
anchor='n'
)
# 更新滚动区域
self.display_canvas.configure(scrollregion=(
0, 0, 800, total_height + 20))
self.status_var.set(f"已转换 {len(text)} 个字符")
def export_image(self):
"""导出当前内容为PNG图片"""
try:
from PIL import ImageGrab
# 获取Canvas在屏幕上的坐标
x = self.root.winfo_rootx() + self.display_canvas.winfo_x()
y = self.root.winfo_rooty() + self.display_canvas.winfo_y()
x1 = x + self.display_canvas.winfo_width()
y1 = y + self.display_canvas.winfo_height()
# 截屏并保存
ImageGrab.grab(bbox=(x, y, x1, y1)).save("pinyin_output.png")
self.status_var.set("图片已保存为 pinyin_output.png")
except Exception as e:
messagebox.showerror("导出错误", f"无法保存图片: {str(e)}")
def copy_pinyin(self):
"""复制拼音文本到剪贴板"""
text = self.input_text.get("1.0", tk.END).strip()
if not text:
self.status_var.set("没有内容可复制")
return
try:
pinyins = self.get_pinyin(text)
# 过滤空拼音并拼接
py_str = ' '.join([py for py in pinyins if py])
self.root.clipboard_clear()
self.root.clipboard_append(py_str)
self.status_var.set("拼音已复制到剪贴板")
except Exception as e:
messagebox.showerror("复制错误", f"无法复制拼音: {str(e)}")
if __name__ == "__main__":
root = tk.Tk()
app = PinyinAnnotator(root)
root.mainloop()