🖨️
Flet で証明写真をL判に割り付けるアプリを作ってみる
毎回忘れて Gimp と格闘しているのでツール化。せっかくなので最近話題の Flet を使ってみます。
できたもの
Python しか書いていないのに GUI が!
L判に4枚割り付けます
手順の振り返り
割り付け処理
画像処理には Pillow を使います。事前に pip install
しておきましょう。
処理の該当部分 にコメントで加筆するとこんな感じです。
# 保存時の名前を作るための関数
def with_stem_tail(path:str, tail:str) -> str:
target = Path(path)
return str(target.stem + tail + target.suffix)
# メイン処理。対象ファイルのパスと出力先、印刷時の証明写真の幅、出力ファイルのサイズ上限を指定。
def allocate(path:str, out_dir:str, photo_width_mm:int=30, max_frame_width:int=2000):
# 保存先のパス
out_path = Path(out_dir, with_stem_tail(path, "_print"))
# 画像とその情報を読み込む
img = Image.open(path)
img_width, img_height = img.size
# 証明写真が印刷時に何mmになるかを基準に、台紙となる画像のサイズを計算する
frame_width = int(img_width * 89 / int(photo_width_mm)) # L判は幅89mm
frame_height = int(frame_width * 1.43) # L判の縦横比
# 台紙となる白画像を生成
frame = Image.new("RGB", (frame_width, frame_height), (255,255,255))
# 台紙の5%は余白を開けたい
margin_x = int(frame_width * 0.05)
margin_y = int(frame_height * 0.05)
# 証明写真を四隅に乗せていく
for x in (margin_x, (frame_width - img_width - margin_x)):
for y in (margin_y, frame_height - img_height - margin_y):
frame.paste(img, (x, y))
# 証明写真のサイズが大きいと台紙のサイズが巨大になりファイルサイズも膨れ上がるので最大ピクセルを超える場合にリサイズ
if frame.width > max_frame_width:
frame = frame.resize((max_frame_width, int(frame.height * max_frame_width / frame_width)))
# 保存
frame.save(out_path, quality=95)
GUI 部分
公式ドキュメント が親切です。
pip install flet
でインストールしたら、main
関数の中にひと通りの命令を書いて GUI を定義し、最後に .app()
で呼び出します。
以下、 import flet as ft
とした前提で書いていきます。
レイアウトの考え方
-
ft.Row(controls=[])
に渡されたコントロールは横並びの「行」として扱われる - 行をさらにリストに格納して
ft.Column(controls=[])
に渡すことで縦並びの「列」となる
簡単なアプリであれば、処理ごとに行を作っていき、最後に列にまとめて page.add()
するという書き方が一番楽そうです。
コントロールの Ref は、こうして最後にまとめて page
に追加するケースを考えると理解が進むかもしれません。
ダイアログ関連
- ダイアログの処理が完了したときに呼ばれる処理を用意してから、
- ダイアログのコントロールを作って、
- ダイアログを表示する関数を用意し、
- ボタンのコントロールから呼び出せるようにする
という手順で作るので少し直観に反しているような気もします。
ここで、 page.overlay.append(file_picker)
としなくてはいけない理由が最初はわからなかったのですが、試しにコメントアウトしてみると下記のエラー。
Exception: Control must be added to the page first.
どうやらコントロールはすべて page
に何かしらの形で紐づけておかなくてはいけないようです。
単一バイナリに書き出す
python main.py
で実行して問題ないようなら、exe 形式で書き出しましょう。
下記コマンドを実行するとビルド処理が走り、 build
と dist
というディレクトリが作られます。
flet pack main.py --name (好きなファイル名).exe
dist
内に最終的なバイナリファイルが生成されます。
Discussion