はじめに

こんにちは、s-yamaguchiです。
自分は結構なLinux育ちなのでCUIには全く抵抗がないのですが、プライベートで簡単なスクリプトを作った際に「GUIがあってボタンを押して実行するようなもののほうが嬉しい」ということを言われたことがあります。
ですので、今回は

  • pythonで作った簡単なスクリプトにGUIをつける
  • なにか自分の趣味に沿ったソフトウェアを↑の技術を利用して作ってみる

ということをしてみようと思います。
pythonの組み込みライブラリで一番簡単に導入できそうという理由で、tkinterを使って実装してみようと思います。

tkinter: https://docs.python.org/ja/3/library/tkinter.html

  1. 簡単なスクリプトに実行ボタンをつけてみる
  2. レイアウトを作成してみる
  3. 趣味のためのソフトウェアを作成してみる
  4. 感想

という順番で解説していこうと思います。

pythonで作成したスクリプトにGUIをつけてみる

pythonで作った簡単なスクリプトにGUIをつけて、ボタンを押すと実行するようなものを作ろうと思います。
バッチ処理やAPIを叩いて何かしらの出力をするという想定で、ボタンを押すとファイルに + の文字を追記していくアプリを作ります。

app.py

#!/usr/bin/env python
# -*- coding: utf8 -*-
import tkinter as tk
from tkinter import ttk
import batch


def main() -> None:
    # 大元になる root のオブジェクトを作成します
    root = tk.Tk()
    # 起動時のウィンドウのサイズを指定します
    root.geometry("320x240")
    # ウィンドウのタイトルを指定します
    root.title("テスト01")
    # GUIのスタイルを指定します
    s = ttk.Style()
    s.theme_use('default')
    # テキストラベルを root の上に配置します
    lb = tk.Label(root, text="練習01")
    # 押すと run_batch を実行するボタンを root の上に配置します
    bt = tk.Button(root, text="実行", command=run_batch)
    # LabelとButtonを pack メソッドを使用して表示します
    lb.pack()
    bt.pack()
    # GUIアプリのためのループを実行します
    root.mainloop()


def run_batch() -> None:
    # ボタンが押されると起動するメソッド
    batch.main()


if __name__ == "__main__":
    main()

batch.py

def main() -> None:
    with open("./batch_out.txt", "a") as f:
        print("+", end="", file=f)
python3 app.py

で起動すると以下のGUIが出てきます。

--_01

ボタンを押すと batch_out.txt+ が追記されていきます。

Frameを重ねてレイアウトを作ってみる

tkinterではFrameを重ねたり並べることでレイアウトを作成します。

--_02_00

↑の画像のイメージの並びでフレームを重ねてレイアウトを実装しようと思います。

app.py

#!/usr/bin/env python
# -*- coding: utf8 -*-
import tkinter as tk
from tkinter import ttk


def main() -> None:
    # 大元になる root のオブジェクトを作成します
    root = tk.Tk()
    # 起動時のウィンドウのサイズを指定します
    root.geometry("400x400")
    # ウィンドウのタイトルを指定します
    root.title("テスト01")
    # GUIのスタイルを指定します
    s = ttk.Style()
    s.theme_use('default')
    # 上下のフレームを作成します
    top_frame = tk.Frame(root, bg="#F00", width=400, height=200)
    bottom_frame = tk.Frame(root, width=400, height=200)
    # 下のフレームの上に左右のフレームを作成します
    left_frame = tk.Frame(bottom_frame, bg="#00F", width=200, height=200)
    right_frame = tk.Frame(bottom_frame, bg="#FF0", width=200, height=200)
    # 左右のフレームを pack します
    left_frame.pack(side="left")
    right_frame.pack(side="left")
    # 上下のフレームをpackします
    top_frame.pack(side="top")
    bottom_frame.pack(side="top")
    # GUIアプリのためのループを実行します
    root.mainloop()


if __name__ == "__main__":
    main()
python3 app.py

で実行すると先程のレイアウト図と同じものが表示されます。

--_02_01

htmlのボックスレイアウトに近い概念で作られているように見えたので、比較的簡単に作れてよかったです。

趣味のソフトウェアを作成してみる

唐突ですが、最近マジックザギャザリングというカードゲームを始めました。
カードの値段が日々変動するので、カード資産の管理をするソフトウェアがほしいと思ったので、今まで解説した内容を応用して作成してみようと思います。

機能

機能について画面を交えて解説します。

  1. 持っているカードと欲しいカードを一覧化したトップ画面
    top

  2. 持っているカードの管理
    collection

  3. 欲しいカードの管理
    wishlist

  4. カード情報の登録、削除
    edit_card
    delete

  5. 価格情報の登録
    edit_value

  6. 価格推移のグラフ化
    graph

  7. カードのデータをcsvで入力(トップ画面のメニューから実行する)

  8. 値段のデータをcsvで入力(トップ画面のメニューから実行する)

  9. 各種データはjsonでローカルに保存

以上が機能です。
元々はもっと機能が少ない予定だったのですが、いざ自分で使ってみることを考えると作り続けるにつれて機能が増えてしまい、最初の方に実装した箇所のリファクタリングをするようなことが多発していました。

実装するにあたって気をつけたこと

実装するにあたって気をつけたことは

  • 各画面をクラス化して管理できるようにする
  • ページのコントローラーを作成してページ遷移の制御をFrameに持たせないようにする
  • 流用できるFrameはコンポーネント化して複数の画面で流用する
  • リスト表示はtkinterのTreeViewという機能で実装する

です。
また、このソフトウェアで汎用的に使えるなと思ったポイントは

  • ファイルの入出力を画面上のデータに反映させる。
  • pythonで実装された、グラフ等の画像の出力をtkinter上のGUIにのせられる。
  • (スクレイピングは無断で行うのはあまり良くないので今回は実装していませんが)pythonでの実装が簡単とされていそうな、rest APIでのデータ取得やスクレイピングとGUIを組み合わせることができそう。

あたりだと思います。

感想

「簡単なスクリプトにGUIをもたせる」という用途だと、簡単に実装できてとても適していると思いました。
「CUIに抵抗がある方向けにスクリプトのインターフェースを共有する」という場面で活躍できるかと思いました。
ただし、複数のページを持っているようなアプリケーションを作成するとなると、各ページのクラス化や共通のフレームの実装方針に気をつけないと、コードを管理できなくなってしまう恐れがかなりあると思ったので、他のフレームワークを利用したほうが良いのかなと思いました。

先日投稿した内容と重なる部分ではあるのですが、「pythonで簡単なスクリプトを作成する」というのはChatGPTの得意分野でもあるので、バックエンドはAIに任せてフロント側を整えてあげる方法で効率化ができるかもしれません。

あとは、余ってるカードって余ってるなりに値段がつかないんだなあとcsvのデータを作りながら少し残念な気持ちでした...
ここまで読んでいただいてありがとうございました。