PythonのGUIアプリをファイルひとつで実行する

# Pythonで書いたGUIアプリを実行ファイルにすると便利なのではないだろうか？

## 何がしたいのか
　この文章は、Pythonで作ったアプリを広くみんなに使ってもらいたい、そんな思いを実現するための記事です。
　ここではWindowsを対象とします。MacやLinuxでも同様にできるようですが、試していません。
　Pythonは、コードを書いて実行するのはお手軽なのですが、他の人にPythonのアプリを使ってもらうのはなかなか大変です。
　まず、Pythonを入れてもらわなければいけません。この段階でハードルが高すぎるのですが、その次にコマンドラインでPythonのアプリを実行してもらわなければいけません。
　環境さえ作れれば良いのですが、その環境を作成するのに手間がかかり、恐らく使うところまでは行きつけそうにありません。
　ならば普通のWindowsアプリのように、GUIがあり、ファイルひとつで実行できれば作ったアプリを活用してもらうのが容易になりそうです。

## 必要なもの

 今回使用するのは以下です。
- Python
- tkinter
- Pyinstaller

　また、必須ではありませんが開発環境としてVisual Studio Codeがあると便利です。
　PythonとVScodeのインストール方法は下記リンクを参照してください。

https://qiita.com/cmssai/items/38dea4c5eb5efb52d45a

https://qiita.com/cmssai/items/cde9080e32b7dfd75030

https://qiita.com/cmssai/items/82f8ff73dca573354e9d

## PythonでGUIアプリ

　PythonでGUIアプリを作る手段はいくつかありますが、ここではtkinter（ティーケーインター）を使用します。
　tkinterは、Pythonの標準ライブラリに入っており追加インストールが必要ありません。
　tkinterのドキュメントは下記リンクを参照してください。
　　[Tk を用いたグラフィカルユーザインターフェイス](https://docs.python.org/ja/3.9/library/tk.html)

　ウインドウを表示するプログラムは以下のようになります。

``` window.py
from logging import root
import tkinter as tk

root = tk.Tk()
root.title('ウインドウ表示')
root.geometry('320x240')
root.mainloop()
```

## Pythonのコードを実行ファイル化

　Pythonで作ったプログラムを実行ファイルにするにはPyinstallerを使います。
　PyinstallerはPythonアプリとそのすべての依存ファイルを1つのファイルにしてくれます。
　Pyinstallerのマニュアルは下記リンクを参照して下さい。英語ですが・・・(汗)
　　[PyInstaller Manual](https://pyinstaller.readthedocs.io/en/stable/)

　Pyinstallerを使用するにはまずインストールします。ここでは仮想環境を作成してインストールします。

```
PS D:\project\desktop> python -m venv venv
PS D:\project\desktop> .\venv\Scripts\activate
(venv) PS D:\project\desktop> pip install pyinstaller
```

　先ほどのプログラムを実行ファイルにするには以下のコマンドを実行します。最後にsuccessfullyが表示されれば出来上がりです。

```
(venv) PS D:\project\desktop> pyinstaller window.py --onefile --noconsole
・
・
・
59127 INFO: Building EXE from EXE-00.toc completed successfully.
```

　distフォルダが作成され、その中に実行ファイルができています。
　出来上がった実行ファイルはPythonがインストールされていないPCでも実行することができます。
　Pyinstallerはクロスコンパイラではないため、Windowsで作成するとWindowsでのみ使用できる実行ファイルとなります。

　ともあれ、これでPythonでGUIアプリを作ってファイルひとつで実行することができるようになりました。

## おまけ

　GUIアプリの例としてサイコロアプリを作ってみました。

``` dice.py
from logging import root
from struct import pack
from os import system
from tkinter import ttk
import tkinter as tk
import random

def roll_dice():
    '''
    サイコロを振る
    '''
    count = int(cb.get())   # サイコロの数を取得
    total = 0               # 合計値
    history = []            # サイコロの出目
    for no in range(count):
        d = random.randint(1, 6)
        total += d
        history.append(d)
    lbl['text'] = f'{total}\r\n{history}'
    return

'''
ウインドウを作成
サイコロの個数選択と結果表示、サイコロを振るボタンを配置する
'''
root = tk.Tk()
root.title('サイコロ')
root.geometry('320x240')

guidemsg = tk.Label(root,
            text='サイコロの数を選択してください')
count_nums = tuple(no for no in range(1, 11))
cb = ttk.Combobox(root,
            width=6,
            state='readonly',
            values=count_nums)
cb.current(0)
lbl = tk.Label(root,
            text='\r\n[ ]',
            font=('system', 20))
btn = tk.Button(root,
            text='サイコロを振る',
            command=roll_dice)

guidemsg.pack(pady=20)
cb.pack()
lbl.pack(pady=10)
btn.pack()

root.mainloop()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/5aa58b92-e239-1e39-2c7f-efe64831bb6d.png)