邊緣系統VLM視覺理解推論實作工作坊
|

細談「春仔產生器」的專案拆解

   
作者:Ted Lee

我們在《用生成式 AI 打造「春仔」產生器》一文中已完整介紹了使用 Claude 來生成春仔的 Python 程式碼的完整過程了。本文再深入增補專案程式解析的三大理路(圖 1):

  1. 加註(annotation):在「程式流程圖」與「函式呼叫圖(call graph)」上標示對應程式碼的行號以加強對程式架構的理解。
  2. 萃取(extraction):從專案程式中截取出「基元(fundamental elements)」──開啟 Tkinter 視窗(另存為「開視窗.py」)、視窗的 UI 設計(另存為「UI.py」)、按鈕事件的處理,update)_text()、春仔中的菱形圖案繪製,draw_diamond()。
  3. 取核:將專案最核心的關鍵演算法找出──春仔中動態吉祥話文字的處理,calculate_font_size()。

圖1:程式碼解析三軸線:加註、萃取、取核

我們使用 Claude 生成春仔產生器的完整 Python 程式碼如下:

春仔產生器.py

# -*- coding: utf-8 -*-

"""

春仔視窗應用程式

功能:繪製紅底燙金花邊的菱形,並可輸入吉祥話和作者名稱

日期:2025/3/11

"""

import tkinter as tk

from tkinter import ttk

import math

# 全域變數設定

WINDOW_WIDTH = 800

WINDOW_HEIGHT = 600

DIAMOND_SIZE = 300 # 菱形大小基準值

BORDER_WIDTH = 10 # 燙金花邊寬度

# 繪製菱形函式

def draw_diamond(canvas, size, border_width):

"""

在畫布上繪製指定大小的紅底燙金花邊菱形

參數:

canvas: tkinter畫布物件

size: 菱形的尺寸

border_width: 燙金花邊的寬度

回傳值:

菱形四個頂點座標

"""

# 取得畫布中心點

center_x = WINDOW_WIDTH // 2

center_y = WINDOW_HEIGHT // 2

# 計算菱形頂點座標

points = [

(center_x, center_y - size // 2), # 上頂點

(center_x + size // 2, center_y), # 右頂點

(center_x, center_y + size // 2), # 下頂點

(center_x - size // 2, center_y) # 左頂點

]

# 繪製紅色內部

canvas.create_polygon(points, fill="#FF0000", outline="")

# 繪製燙金花邊 (外層邊框)

outer_points = [

(center_x, center_y - (size + border_width) // 2),

(center_x + (size + border_width) // 2, center_y),

(center_x, center_y + (size + border_width) // 2),

(center_x - (size + border_width) // 2, center_y)

]

canvas.create_polygon(outer_points, fill="#DAA520", outline="")

canvas.create_polygon(points, fill="#FF0000", outline="")

return points

# 計算適合菱形內的字型大小

def calculate_font_size(canvas, text, points, max_size=100, min_size=8):

"""

計算文字適合放入菱形內的最大字型大小

參數:

canvas: tkinter畫布物件

text: 要顯示的文字

points: 菱形的頂點座標

max_size: 最大字型大小

min_size: 最小字型大小

回傳值:

適合的字型大小

"""

# 計算菱形寬度和高度

diamond_width = points - points

diamond_height = points - points

# 考慮菱形形狀,可用空間更小

usable_width = diamond_width * 0.7

usable_height = diamond_height * 0.7

# 二分法查找合適的字型大小

size = max_size

lower_bound = min_size

upper_bound = max_size

while upper_bound - lower_bound > 1:

temp_font = ("微軟正黑體", size, "bold")

text_width = canvas.create_text(0, 0, text=text, font=temp_font, anchor=tk.NW)

bbox = canvas.bbox(text_width)

canvas.delete(text_width)

if bbox is None:

upper_bound = size

size = (upper_bound + lower_bound) // 2

continue

text_width = bbox - bbox

text_height = bbox - bbox

if text_width <= usable_width and text_height <= usable_height:

lower_bound = size

else:

upper_bound = size

size = (upper_bound + lower_bound) // 2

return lower_bound

# 更新畫布上的吉祥話和作者

def update_text(canvas, greeting_var, author_var, diamond_points):

"""

更新畫布上的吉祥話和作者文字

參數:

canvas: tkinter畫布物件

greeting_var: 吉祥話變數

author_var: 作者變數

diamond_points: 菱形的頂點座標

"""

# 清除先前的文字

canvas.delete("greeting")

canvas.delete("author")

# 取得當前輸入的文字

greeting = greeting_var.get()

author = author_var.get()

if greeting:

# 計算吉祥話的合適字型大小

greeting_font_size = calculate_font_size(canvas, greeting, diamond_points)

greeting_font = ("微軟正黑體", greeting_font_size, "bold")

# 繪製吉祥話 (置中位置,稍微往上一點)

center_x = WINDOW_WIDTH // 2

center_y = WINDOW_HEIGHT // 2 - 20

canvas.create_text(center_x, center_y, text=greeting, font=greeting_font,

fill="#DAA520", tags="greeting")

if author:

# 計算作者的合適字型大小

author_font_size = min(24, calculate_font_size(canvas, author, diamond_points) - 4)

author_font = ("微軟正黑體", author_font_size)

# 繪製作者 (置於菱形下方)

center_x = WINDOW_WIDTH // 2

center_y = WINDOW_HEIGHT // 2 + 70

canvas.create_text(center_x, center_y, text=author, font=author_font,

fill="#DAA520", tags="author")

# 主程式函式

def main():

"""

主程式函式,建立視窗和控制項

"""

# 建立主視窗

root = tk.Tk()

root.title("春仔 - 新年吉祥賀卡")

root.geometry(f"{WINDOW_WIDTH}x{WINDOW_HEIGHT}")

# 建立主框架

main_frame = ttk.Frame(root)

main_frame.pack(fill=tk.BOTH, expand=True)

# 建立畫布

canvas = tk.Canvas(main_frame, bg="#FFF8DC")

canvas.pack(fill=tk.BOTH, expand=True)

# 繪製菱形

diamond_points = draw_diamond(canvas, DIAMOND_SIZE, BORDER_WIDTH)

# 建立輸入框架

input_frame = ttk.Frame(root, padding="10")

input_frame.pack(fill=tk.X)

# 建立吉祥話輸入

ttk.Label(input_frame, text="吉祥話:").grid(row=0, column=0, padx=5, sticky=tk.W)

greeting_var = tk.StringVar()

greeting_entry = ttk.Entry(input_frame, textvariable=greeting_var, width=40)

greeting_entry.grid(row=0, column=1, padx=5)

greeting_entry.insert(0, "恭賀新春")

# 建立作者輸入

ttk.Label(input_frame, text="作者:").grid(row=0, column=2, padx=5, sticky=tk.W)

author_var = tk.StringVar()

author_entry = ttk.Entry(input_frame, textvariable=author_var, width=15)

author_entry.grid(row=0, column=3, padx=5)

# 建立更新按鈕

update_button = ttk.Button(input_frame, text="更新內容",

command=lambda: update_text(canvas, greeting_var, author_var, diamond_points))

update_button.grid(row=0, column=4, padx=10)

# 初始化顯示

update_text(canvas, greeting_var, author_var, diamond_points)

# 啟動主迴圈

root.mainloop()

# 程式入口點

if __name__ == "__main__":

main()

一、開 Tkinter 視窗

將「春仔產生器.py」以單行註解 # 和多行註解 ‘’’ ‘’’ 剔除暫時不相關的程式碼後,我們可以得到以下的「開視窗.py」及其執行結果(圖 2):

開視窗.py

# -*- coding: utf-8 -*-

"""

春仔視窗應用程式

功能:繪製紅底燙金花邊的菱形,並可輸入吉祥話和作者名稱

日期:2025/3/11

"""

import tkinter as tk

from tkinter import ttk

import math

# 全域變數設定

WINDOW_WIDTH = 800

WINDOW_HEIGHT = 600

DIAMOND_SIZE = 300 # 菱形大小基準值

BORDER_WIDTH = 10 # 燙金花邊寬度

# 主程式函式

def main():

"""

主程式函式,建立視窗和控制項

"""

# 建立主視窗

root = tk.Tk()

root.title("春仔 - 新年吉祥賀卡")

root.geometry(f"{WINDOW_WIDTH}x{WINDOW_HEIGHT}")

# 建立主框架

main_frame = ttk.Frame(root)

main_frame.pack(fill=tk.BOTH, expand=True)

# 啟動主迴圈

root.mainloop()

# 程式入口點

if __name__ == "__main__":

main()

本文為會員限定文章

立即加入會員! 全站文章無限看~

                               

已經是會員? 按此登入

只需不到短短一分鐘...

輸入您的信箱與ID註冊即可享有一切福利!

會員福利
1

免費電子報

2

會員搶先看

3

主題訂閱

4

好文收藏

Author: Ted Lee

從工程師轉任中學教師,又為了捍衛教育理念,投身成為 STEAM 教育工作者,自稱「無可救藥的人文教育理想主義者」的李俊德(Ted Lee)。

Share This Post On
468 ad

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *