liuchangng 发表于 2024-4-9 16:16

汉字笔画生成

本帖最后由 liuchangng 于 2024-4-19 15:51 编辑

一,简介
小孩上小学,学习汉字书写,为了掌握正确的书写顺序,编写了这个小工具.

二,代码展示

import logging
import os
import re
import time

import flet
from PIL import Image
from flet import (
    Page,
    UserControl,
    Text,
    ListView
)
from flet_core import AlertDialog, TextButton
from playwright.sync_api import sync_playwright# 下载浏览器 playwright install chromium

# 1. 初始化日志记录器
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 2. 定义浏览器User-Agent
USER_AGENT = \
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'


class ChineseBiHua(UserControl):
    """汉字笔划控件"""


    def __init__(self, page: Page, persistent_browser: bool = True):
      super().__init__(page)
      self.page = page
      self.persistent_browser = persistent_browser# 是否非无痕模式,默认无痕模式

      # 3. 初始化汉字输入文本框
      self.chinese_word_input = flet.TextField(
            label='待输入汉字(可以空格分割;逗号分隔;不加任何符号.)',
            value='无',
            width=615,
            max_lines=5,
            border_radius=10
      )

      # 4. 初始化汉字图片排序下拉菜单
      self.word_sort_dropdown = flet.Dropdown(
            height=55,
            width=150,
            border_radius=20,
            label="排序",
            text_size=12,
            hint_text="选择需要的顺序",
            value="1",
            options=[
                flet.dropdown.Option(key="1", text="汉字顺序"),
                flet.dropdown.Option(key="2", text="字典顺序"),
            ],
            autofocus=True,
      )

      # 5. 定义显示笔划图片的控件,可以滚动
      self.bihua_scroll_viewer = ListView(expand=1, controls=[flet.Image(
            src='./images/笔画总表.png',
            height=600,
            fit=flet.ImageFit.CONTAIN,
      )], height=600, auto_scroll=True)

    def build(self):
      # 5. 构建页面布局
      layout = [
            # 页面标题
            flet.Row(
                controls=,
                alignment=flet.MainAxisAlignment.CENTER,
            ),
            # 汉字输入区域
            flet.Row(controls=),
            # 操作按钮区域
            flet.Row(
                controls=[
                  self.word_sort_dropdown,
                  # 生成笔划按钮
                  flet.ElevatedButton(
                        "汉字笔划",
                        height=55,
                        icon=flet.icons.SAVE,
                        on_click=self.generate_bi_hua,
                  ),
                ],
                alignment=flet.MainAxisAlignment.END,
            ),

            # 显示笔划图片区域
            flet.Row(controls=)
      ]

      return flet.Column(controls=layout)

    def generate_bi_hua(self, e):
      """生成汉字笔划事件处理函数"""
      # 6. 初始化Playwright环境
      with sync_playwright() as playwright:
            if self.persistent_browser:# 无痕模式
                browser = playwright.chromium.launch(headless=False, args=['--start-maximized'])
                page = browser.new_context(user_agent=USER_AGENT).new_page()
                page.set_viewport_size(viewport_size={'width': 1920, 'height': 1080})# 设置浏览器窗口大小
            else:
                browser = playwright.chromium.launch_persistent_context(# 非无痕模式
                  executable_path=r'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe',# 浏览器路径
                  channel='msedge',# 浏览器类型
                  headless=False,
                  user_data_dir=r"C:\Users\Administrator\AppData\Local\Microsoft\Edge\User Data\Default",# 浏览器数据路径
                  accept_downloads=True,
                  args=['--start-maximized'],# 设置浏览器窗口大小
                  no_viewport=True,
                )
                page = browser.new_page()
            # 获取待处理汉字
            words = re.sub(r'[^\u4e00-\u9fff]', '', self.chinese_word_input.value)
            logging.info(f'汉字: {words}')

            # 去除重复汉字并按指定顺序排序
            word_list = list(set(words))
            if self.word_sort_dropdown.value == "2":
                word_list.sort()

            # 逐个生成并保存单个汉字笔划图片
            for word in word_list:
                self.generate_single_bi_hua(page, word)
                time.sleep(1)

            # 合成所有汉字笔划图片
            concat_images(, direction='vertical')

            # 删除图片
            for item in word_list:
                os.remove(f'./images/{item}.png')

            # 更新界面上的笔划图片为合成后的图片
            self.bihua_scroll_viewer.controls.clear()# 清空已存在的图片控件
            self.bihua_scroll_viewer.controls.append(flet.Image(
                src='./images/合成.png',
                fit=flet.ImageFit.CONTAIN
            ))
            self.bihua_scroll_viewer.update()

            # 弹出提示对话框并打开图片目录
            self.show_completion_dialog_and_open_directory()

            # 关闭浏览器
            browser.close()

    def generate_single_bi_hua(self, page, word):
      """生成单个汉字笔划图片"""
      url = f"https://hanyu.baidu.com/s?wd={word}&ptype=zici"
      try:
            # 访问指定URL
            page.goto(url)

            # 等待笔划元素加载并截图
            element_selector = '.word-stroke-wrap'
            page.wait_for_selector(element_selector, timeout=5000)
            element = page.locator(element_selector)
            bounding_box = element.bounding_box()
            logging.info(f'{word}: {bounding_box}')
            if bounding_box:
                x, y, width, height = (bounding_box['x'], bounding_box['y'], bounding_box['width'],
                                       bounding_box['height'])
                page.screenshot(path=f'./images/{word}.png', full_page=True,
                              clip={'x': x, 'y': y, 'width': width, 'height': height})
                time.sleep(0.5)
            else:
                logging.warning(f"{word}没有找到笔划!")
      except Exception as e:
            logging.error(f"{word}生成笔划时发生错误,原因:{e}")

    def show_completion_dialog_and_open_directory(self):
      """显示完成提示对话框并打开图片目录"""

      def close_dlg(e):
            dialog.open = False
            os.startfile(os.path.abspath('./images'))
            self.page.update()

      # 创建提示对话框
      dialog = AlertDialog(
            title=Text('提示:'),
            actions=[
                TextButton("确定", on_click=close_dlg)
            ],
            actions_alignment=flet.MainAxisAlignment.END,
      )
      self.page.dialog = dialog
      dialog.content = Text('合成图片完成!')
      dialog.open = True
      self.page.update()


def concat_images(images, direction='horizontal', separator_color=(0, 0, 0), separator_size=3):
    """
    合成图片

    :param images: 待合成图片列表
    :param direction: 合成方向(horizontal或vertical)
    :param separator_color: 分割线颜色
    :param separator_size: 分割线大小
    """
    # 打开所有图像并获取尺寸
    images =
    widths, heights = zip(*(i.size for i in images))
    logging.info(f'widths: {widths}, heights: {heights}')

    # 计算拼接后图像的尺寸
    if direction == 'horizontal':
      total_width = sum(widths) + separator_size * (len(images) - 1)
      max_height = max(heights)
      new_size = (total_width, max_height)
    else:
      max_width = max(widths)
      total_height = sum(heights) + separator_size * (len(images) - 1)
      new_size = (max_width, total_height)

    # 创建新图像并将所有图像拼接到上面
    new_image = Image.new('RGB', new_size, color=separator_color)
    offset = 0
    for img in images:
      if direction == 'horizontal':
            new_image.paste(img, (offset, 0))
            offset += img.size + separator_size
      else:
            new_image.paste(img, (0, offset))
            offset += img.size + separator_size

    new_image.save('./images/合成.png')


def main(page: flet.Page):
    # 10. 定义页面属性和布局
    page.title = "汉字笔画"
    page.window_width = 650
    page.window_height = 850
    page.scroll = True
    page.window_maximizable = False
    page.window_minimized = False
    page.window_center()
    page.update()

    # 11. 创建并添加汉字笔划控件到页面
    chinese_bihua = ChineseBiHua(page)
    page.add(chinese_bihua)


if __name__ == '__main__':
    flet.app(target=main)


三,本地运行

1,安装依赖
```shell
pip install flet==0.21.2 playwright==1.42.0 pillow==10.2.0
```

2,安装浏览器
```shell
playwright install chromium
```
3,运行
```shell
python main.py
```

四,可执行文件地址
版本hanzibihuaV20240415.zip
123网盘:
https://www.123pan.com/s/Gvawjv-TwOph.html提取码:52pj
百度网盘:
链接:https://pan.baidu.com/s/1ibSbeemyyir_cb-k8K0fCw?pwd=1024
提取码:1024
说明:
1)增加拼音,部首,笔画数
2)效果图



版本hanzibihuaV20240410.zip
https://www.123pan.com/s/Gvawjv-PaOph.html提取码:52pj
说明:
1)输入汉字或句子生成笔画合成图片
2)效果图










csclc 发表于 2024-4-10 08:05

这个非常好,分享的很是有水准

nccdap 发表于 2024-4-10 08:43

D:\Python>pip install flet
ERROR: Could not find a version that satisfies the requirement flet (from versions: none)
ERROR: No matching distribution found for flet

D:\Python>playwright install chromium
'playwright' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

D:\Python>pip3 install flet
ERROR: Could not find a version that satisfies the requirement flet (from versions: none)
ERROR: No matching distribution found for flet

D:\Python>pip install flet -i https://pypi.tuna.tsinghua.edu.cn/simple/
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple/
ERROR: Could not find a version that satisfies the requirement flet (from versions: none)
ERROR: No matching distribution found for flet

D:\Python>pip3 install flet -i https://pypi.tuna.tsinghua.edu.cn/simple/
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple/
ERROR: Could not find a version that satisfies the requirement flet (from versions: none)
ERROR: No matching distribution found for flet

Corgibro 发表于 2024-4-10 04:54

这个也太强了,练字好帮手

hhxx23 发表于 2024-4-10 05:44

这个不错,方便!

jinqiaoa1a 发表于 2024-4-10 06:38

真的很不错,感谢楼主分享

66688891zgl 发表于 2024-4-10 07:17

不错。这是一个好帮手。

blindcat 发表于 2024-4-10 07:19

这个厉害了,我现在都不会写字了

a12345r 发表于 2024-4-10 08:00

不懂编程,请问怎么使用它?谢谢!

Wapj_Wolf 发表于 2024-4-10 08:02

py都写了这么多行代码,这是真的牛。

woajs 发表于 2024-4-10 08:07

感谢楼主分享!
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 汉字笔画生成