基于python3 flet库的对联生成工具
前言
python3 的 flet 库是一个非常好用的页面工具库,既可以作为软件也可以作为网页打开。
目前基于网络上找到的对联生成工具和flet页面,做了一个简单的对联生成工具,博君一笑。
如有侵权,请联系作者,谢谢。
正文
源代码
对联生成工具
代码结构:
font -- 字体路径
书体坊颜体.ttf -- 字体文件
img -- 对联背景路径
bg.png -- 对联背景
out_dir -- 输出路径
genWord.py -- 对联生成工具
main.py -- flet 主程序
genWord.py
import io
import numpy as np
import requests
from PIL import Image, ImageFont, ImageDraw
def genMyword(text, path_to_ttf = './font/书体坊颜体.ttf'):
# 字体
# path_to_ttf = './font/书体坊颜体.ttf'
# font-TrueType字体文件。在Windows下,如果在该文件名中找不到该文件,则加载程序还会在Windows fonts /目录中查找。
# size-请求的大小(以磅为单位)。
# index-要加载的字体(默认为第一个可用的字体)。
# encoding-使用哪种字体编码(默认为Unicode)。
fontSize=400
font = ImageFont.truetype(path_to_ttf, size=fontSize)
# 透明图片
imgSide=500
# A-透明度
img = Image.new('RGBA', (imgSide,imgSide), '#ffffff00')
# 文字位置
xPos = (imgSide - fontSize)/2+50
# yPos = (imgSide - fontSize)/2
yPos = 0 + 80
print(xPos,yPos)
# 写文字
draw = ImageDraw.Draw(img)
draw.text(xy=(xPos, yPos), text=text, font=font, fill=(0,0,0,255))
# 输出
# img.show()
# img.convert("RGBA").save("tst.png")
return img
def get_word(ch, quality, img="./img/bg.png", path_to_ttf = './font/书体坊颜体.ttf'):
"""获取单个汉字(字符)的图片
ch - 单个汉字或英文字母(仅支持大写)
quality - 单字分辨率,H-640像素,M-480像素,L-320像素
"""
if ch == 'bg':
# fp = io.BytesIO(requests.post(url='http://xufive.sdysit.com/tk', data={'ch':ch}).content)
# im = Image.open(fp)
im = Image.open(img)
else:
im = genMyword(ch, path_to_ttf)
w, h = im.size
print(ch,w,h)
if quality == 'M':
w, h = int(w*0.75), int(0.75*h)
elif quality == 'L':
w, h = int(w*0.5), int(0.5*h)
return im.resize((w,h))
def get_bg(quality, img="./img/bg.png"):
"""获取春联背景的图片"""
return get_word('bg', quality, img=img)
def write_couplets(text, HorV='V', quality='L', img="./img/bg.png", path_to_ttf = './font/书体坊颜体.ttf', out_file=None):
"""生成春联
text - 春联内容,以空格断行
HorV - H-横排,V-竖排
quality - 单字分辨率,H-640像素,M-480像素,L-320像素
out_file - 输出文件名
"""
usize = {'H':(640,23), 'M':(480,18), 'L':(320,12)}
bg_im = get_bg(quality)
text_list = [list(item) for item in text.split()]
rows = len(text_list)
cols = max([len(item) for item in text_list])
if HorV == 'V':
ow, oh = 40+rows*usize[quality][0]+(rows-1)*10, 40+cols*usize[quality][0]
else:
ow, oh = 40+cols*usize[quality][0], 40+rows*usize[quality][0]+(rows-1)*10
out_im = Image.new('RGBA', (ow, oh), '#f0f0f0')
for row in range(rows):
if HorV == 'V':
row_im = Image.new('RGBA', (usize[quality][0], cols*usize[quality][0]), 'white')
offset = (ow-(usize[quality][0]+10)*(row+1)-10, 20)
else:
row_im = Image.new('RGBA', (cols*usize[quality][0], usize[quality][0]), 'white')
offset = (20, 20+(usize[quality][0]+10)*row)
for col, ch in enumerate(text_list[row]):
if HorV == 'V':
pos = (0, col*usize[quality][0])
else:
pos = (col*usize[quality][0],0)
# 获取纯文字
ch_im = get_word(ch, quality, img=img, path_to_ttf=path_to_ttf)
# 获取背景
row_im.paste(bg_im, pos)
# 拼合文字和背景
row_im.paste(ch_im, (pos[0]+usize[quality][1], pos[1]+usize[quality][1]), mask=ch_im)
out_im.paste(row_im, offset)
if out_file:
out_im.convert('RGB').save(out_file)
out_im.show()
if __name__ == '__main__':
# text = '普天同庆 欢度春节'
# write_couplets(text, HorV='V', quality='M', out_file='普天同庆.jpg')
# text = '这是横批'
# write_couplets(text, HorV='H', quality='M', out_file=text+'.jpg')
# text = '永'
# write_couplets(text, HorV='V', quality='M', out_file='tst.jpg')
text = '落霞与孤鹜齐飞 秋水共长天一色'
write_couplets(text, HorV='V', quality='M', out_file='{0}.jpg'.format(text))
main.py
# -*- coding:utf-8 -*-
# 对联工具
import flet as ft
import os
from genWord import write_couplets
# 配置文件
class Conf(object):
def __init__(self) -> None:
self.font_dir = "./font"
self.img_dir = "./img"
self.out_dir = "./out_dir"
self.image_name = "{0}/bg.png".format(self.img_dir)
self.fonts = self.list_fonts()
def list_fonts(self)->dict:
"""
遍历文件夹中的字体名称
"""
fonts = {}
for file in os.listdir(self.font_dir):
if os.path.isfile(os.path.join(self.font_dir, file)):
fonts_name = os.path.splitext(os.path.basename(file))[0]
fonts[fonts_name] = file
return fonts
def main(page: ft.Page):
page.title = "对联生成工具"
conf = Conf()
def btn_submit_clicked(e):
"""确认"""
couplet_str = ""
font = ""
h_or_v = ""
quality = "H"
if not txt_couplet.value:
txt_couplet.error_text = "请输入对联内容"
page.update()
return
else:
couplet_str = txt_couplet.value
if not dropdown_fonts.value:
dlg = ft.AlertDialog(
title=ft.Text("Error"),
content=ft.Text("请选择字体")
)
page.dialog = dlg
dlg.open = True
page.update()
return
font = dropdown_fonts.value
if not dropdown_h_or_v.value:
dlg = ft.AlertDialog(
title=ft.Text("Error"),
content=ft.Text("请选择对联方向")
)
page.dialog = dlg
dlg.open = True
page.update()
return
h_or_v = dropdown_h_or_v.value
if not dropdown_quality.value:
dlg = ft.AlertDialog(
title=ft.Text("Error"),
content=ft.Text("请选择对联画质")
)
page.dialog = dlg
dlg.open = True
page.update()
return
quality = dropdown_quality.value
write_couplets(text=couplet_str,
HorV=h_or_v,
quality=quality,
img=conf.image_name,
path_to_ttf="{0}/{1}".format(conf.font_dir, font),
out_file="{0}/{1}.jpg".format(conf.out_dir, couplet_str))
def btn_clean_clicked(e):
"""清空"""
txt_couplet.value = ""
page.update()
return
txt_couplet = ft.TextField(label="请输入对联内容,对联以空格作为间隔")
# 字体下拉框提示
txt_fonts = ft.Text("请选择字体: ")
# 字体下拉框
dropdown_fonts = ft.Dropdown(
width=130,
options=[ft.dropdown.Option(key=conf.fonts[i], text=i) for i in conf.fonts.keys()]
)
# 对联方向提示
txt_h_or_v = ft.Text("请选择对联方向: ")
# 对联方向下拉框
dropdown_h_or_v = ft.Dropdown(
width=100,
options=[
ft.dropdown.Option(key="V", text="竖向"),
ft.dropdown.Option(key="H", text="横向")
]
)
# 画质提示
txt_quality = ft.Text("请选择对联画质: ")
# 画质下拉框
dropdown_quality = ft.Dropdown(
width=100,
options=[
ft.dropdown.Option(key="H", text="高"),
ft.dropdown.Option(key="M", text="中"),
ft.dropdown.Option(key="L", text="低")
]
)
# 确认按钮
btn_submit = ft.ElevatedButton(text="确认", on_click=btn_submit_clicked)
# 清空按钮
btn_clean = ft.ElevatedButton(text="清空", on_click=btn_clean_clicked)
page.add(
# 标题
txt_couplet,
# 对联内容
ft.Row(
[
txt_fonts,
dropdown_fonts
]
),
# 对联方向
ft.Row(
[
txt_h_or_v,
dropdown_h_or_v
]
),
# 对联质量
ft.Row(
[
txt_quality,
dropdown_quality
]
),
# 分割线
ft.Divider()
,
# 按钮
ft.Row(
[
btn_submit,
btn_clean
]
)
)
if __name__ == "__main__":
# ft.app(target=main)
ft.app(target=main, view=ft.AppView.WEB_BROWSER)
效果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App