$30 off During Our Annual Pro Sale. View Details »

Pythonでデスクトップアプリを簡単に作る方法

Jun okazaki
February 29, 2020

 Pythonでデスクトップアプリを簡単に作る方法

PyCon mini Shizuoka で発表する内容のスライドです。
PythonのGUIライブラリPySimpleGUIを使用してデスクトップアプリを作成する方法を紹介します

https://shizuoka.pycon.jp/session/dario_okazaki/

code: https://github.com/okajun35/for_pycon_shizu

Jun okazaki

February 29, 2020
Tweet

More Decks by Jun okazaki

Other Decks in Technology

Transcript

  1. Pythonでデスクトップ
    アプリを簡単に作る方法
    2020年2月27日 オカザキ
    1
    PyCon miniShizuoka 発表用

    View Slide

  2. お品書き
    1. 一部 PythonのGUIについて
    2. 二部 tkinterについて
    3. 三部 PySimpleGUIについて
    4. 四部 PySimpleGUIのアプリの例
    2

    View Slide

  3. 自己紹介
    • オカザキ(@dario_okazaki)
    • 所属:(株)スカラコミュニケーション

    • 職業:サーバーサイドエンジニア
    • PyconJP2017 トーク「Kivyによるアプ
    リケーション開発のすすめ」
    • 長野Python会 with NSEG(2018/7/28)
    「PythonのGUI@2018」
    3

    View Slide

  4. 会社紹介
    • 株式会社スカラコミュニケーションズ
    • https://scala-com.jp/
    • BtoB向けのシステム開発
    • メインの開発はPHP,
    • Python,C#でも開発
    • 所在地:渋谷ヒカリエ(1月~)
    • エンジニア募集中
    4

    View Slide

  5. 問題提起
    私はPythonで○○○がしたい。
    だから○○○は○○○でいい
    5

    View Slide

  6. 今日説明するデスクトップアプリについて
    画面遷移が3枚程度の簡単なアプリを
    想定しています
    6

    View Slide

  7. 質問
    • PythonのGUIライブラリってつかったことありますか?
    • つかった人はどんなライブラリを使われました?
    • You tube liveのコメントに書いてみてください
    7

    View Slide

  8. お品書き
    1. 一部 PythonのGUIについて
    2. 二部 tkinterについて
    3. 三部 PySimpleGUIについて
    4. 四部 PySimpleGUIのアプリの例
    8

    View Slide

  9. PythonでのGUIの立ち位置(1/2)
    9
    JET BRAINSのThe State of Developer Ecosystem 2019のPythonより

    View Slide

  10. PythonでのGUIの立ち位置(2/2)
    JET BRAINSのThe State of Developer Ecosystem 2019のPythonより
    10
    • Pythonを使う上ではメジャーではない

    View Slide

  11. PythonのGUIについて(1/3)
    • ライブラリの数は多いが決定的なものはない
    11
    • Tkinter
    • wxPython
    • PyQt5 ※QT系
    • PySide2 ※QT系
    • pySimplelGUI
    • PyGTK
    • PyFLTK
    • Kivy
    • Eel
    • flexx
    • REMI
    • Electron + Python※2
    • React Native + Transcrypt(altJS)※2
    • Pygame
    • Toga
    ※Qt系はそれぞれ開発元とライセンスが違います
    ※2はライブラリではなくて手法です

    View Slide

  12. PythonのGUIについて(2/3)
    12
    • cefpython
    • PyGObject
    • Pyglet
    • PyGUI
    • libavg
    • Pyforms
    etc・・・

    View Slide

  13. PythonのGUIについて(3/3)
    • その他(Android端末で動くもの)
    • QPython ※Andoridで動くIDE
    • Pydroid3 ※Andoridで動くIDE
    • LINE MessageAPI※Lineアプリ上で動くもの
    • IOSだとPythonistaというアプリがある
    13

    View Slide

  14. 日本のPythonのGUIについて
    • 初心者向けの本でGUIだとPygameとtkinterを使う本が増えて
    きたように感じる
    • 日本だと機械学習、統計などのデータサイエンスの利用例が多
    くGUIはメジャーではない
    14

    View Slide

  15. 検証環境について
    • Windows10
    • Python3.7.6
    ※一部の機能についてはmacOS(Catalina)でも確認
    15

    View Slide

  16. サンプルコードについて
    • サンプルコードはGithubにおいてます
    • https://github.com/okajun35/for_pycon_shizu
    16

    View Slide

  17. お品書き
    1. 一部 PythonのGUIについて
    2. 二部 tkinterについて
    3. 三部 PySimpleGUIについて
    4. 四部 PySimpleGUIのアプリの例
    17

    View Slide

  18. tkinterについて(1/3)
    • Pythonの標準GUI
    • 環境構築が不要
    • Pythonのインストール時に一緒にインストールされる
    • 公式リファレンスにドキュメントがある
    • Tk を用いたグラフィカルユーザインターフェイス
    18

    View Slide

  19. tkinterについて(2/3)
    • Pythonの標準IDEである「IDLE」にも使われている
    • Tcl/TkのTk部分を移植している
    • Tcl/TK自体は初リリースは1998年!
    19

    View Slide

  20. tkinterについて(3/3)
    パーソナルコンピュータの基本ソフトウェアとウィンドウ環境としては Windows,
    macOS, Linux/X-Window など複数のものが使われており、それぞれにウィンドウ
    の 描画などは異なった方法で行われます。これらの OS/ウィンドウ環境の差異を
    吸収 し、共通に使える GUI 用のフレームワークとして Tcl/Tk があります。
    tkinter はこの Tcl/Tk を Python から利用できるようにしたパッケージです
    20
    ~ 京都大学 プログラミング演習 Python 2019 Version2020_02_13_01.pdf から引用 ~

    View Slide

  21. GUIの基本
    GUI 型のアプリケーションでは、メニューやボタンなどによるさ
    まざまな操作を ユーザ自身が選択して利用します。そして、操作
    に対してコンピュータが適切に応 答することを期待します。
    このようなユーザの操作を「イベント」と呼びます。多くの GUI
    型のアプリケーションは GUI 用の「フレームワーク」を利用しま
    す。
    フレームワークはマウスやキーボードの操作を監視してイベントを
    検出し、プロ グラマーによって設定されたイベント処理用のプロ
    グラムを呼び出します。 フレームワークを用いた GUI 型のアプリ
    ケーションではプログラマーは主として 以下のような部分のプロ
    グラミングを担います。
    イベントが発生した際に行う処理の定義 このようなプログラミン
    グをイベントに対する応答を主に記述することからイベン ト駆動
    型 (event-driven) プログラミングと呼びます。
    21
    ~ 京都大学 プログラミング演習 Python 2019 Version2020_02_13_01.pdf から引用 ~

    View Slide

  22. tkinterの基本
    import tkinter
    from tkinter import messagebox
    #ボタンがクリックされたら実行
    def button_click():
    input_value = input_box.get()
    messagebox.showinfo("クリックイベント",input_value + "が入力されまし
    た。")
    #ウインドウの作成
    root = tkinter.Tk()
    root.title("Python GUI")
    root.geometry("360x240")
    #入力欄の作成
    input_box = tkinter.Entry(width=40)
    input_box.place(x=10, y=100)
    #ラベルの作成
    input_label = tkinter.Label(text="ラベル")
    input_label.place(x=10, y=70)
    #ボタンの作成
    button = tkinter.Button(text="実行ボタン",command=button_click)
    button.place(x=10, y=130)
    #ウインドウの描画
    root.mainloop()
    22

    View Slide

  23. tkinterの問題点(1/2)
    import tkinter
    from tkinter import messagebox
    ~~~省略~
    #ウインドウの作成
    root = tkinter.Tk()
    root.title("Python GUI")
    root.geometry("360x120")
    # 名前
    input_name_label = tkinter.Label(text="名前")
    input_name_label.grid(row=1, column=1, padx=10,)
    # 入力欄の作成
    input_name = tkinter.Entry(width=40)
    input_name.grid(row=1, column=2)
    # 住所
    input_address_label = tkinter.Label(text="住所")
    input_address_label.grid(row=2, column=1, padx=10,)
    # 住所入力欄の作成
    input_address = tkinter.Entry(width=40)
    input_address.grid(row=2, column=2)
    # 電話番号
    input_phone_label = tkinter.Label(text="名前")
    input_phone_label.grid(row=3, column=1, padx=10,)
    # 電話番号入力欄の作成
    input_phone = tkinter.Entry(width=40)
    input_phone.grid(row=3, column=2)
    23

    View Slide

  24. tkinterの問題点(2/2)
    • 書き方がPython的でない→忘れ

    • レイアウトが縦、横のグリッド
    で指定するのでよくわからない
    root.geometry("360x240")
    # 入力欄の作成
    input_name = tkinter.Entry(width=40)
    input_name.grid(row=1, column=2)
    # 住所
    input_address_label = tkinter.Label(text="住所")
    input_address_label.grid(row=2, column=1, padx=10,)
    # 住所入力欄の作成
    input_address = tkinter.Entry(width=40)
    input_address.grid(row=2, column=2)
    # 電話番号
    input_phone_label = tkinter.Label(text="名前")
    input_phone_label.grid(row=3, column=1, padx=10,)
    # 電話番号入力欄の作成
    input_phone = tkinter.Entry(width=40)
    input_phone.grid(row=3, column=2)
    24

    View Slide

  25. お品書き
    1. 一部 PythonのGUIについて
    2. 二部 tkinterについて
    3. 三部 PySimpleGUIについて
    4. 四部 PySimpleGUIのアプリの例
    25

    View Slide

  26. PySimpleGUIの紹介
    • https://pysimplegui.readthedocs.io/en/latest/
    • 2018年にできたライブラリー
    • TkinterのラッパーでPythonライクに書けるのが特徴
    • 派生でwxPython、PyQtのラッパーライブラリーも存在
    • 公式では元のライブラリで書くのに比べてコード量が1/2~1/10になると説明
    • Githubでは3,000スター
    • ライセンスはLGPL-3.0
    26

    View Slide

  27. インストール
    • Pure Pythonなのでインストールは簡単
    pip install pysimplegui
    or
    pip3 install pysimplegui
    27

    View Slide

  28. 基本の形 (1/8)
    import PySimpleGUI as sg
    # セクション1 - オプションの設定と標準レイアウト
    sg.theme('Dark Blue 3')
    layout = [
    [sg.Text('Python GUI')],
    [sg.Text('名前', size=(15, 1)), sg.InputText('○○〇×××')],
    [sg.Text('住所', size=(15, 1)), sg.InputText('△△△△村')],
    [sg.Text('電話番号', size=(15, 1)), sg.InputText('xxx-xxx-xxx')],
    [sg.Submit(button_text='実行ボタン')]
    ]
    # セクション 2 - ウィンドウの生成
    window = sg.Window('住所を入力', layout)
    # セクション 3 - イベントループ
    while True:
    event, values = window.read()
    if event is None:
    print('exit')
    break
    if event == '実行ボタン':
    show_message = "名前:" + values[0] + 'が入力されました。¥n'
    show_message += "住所:" + values[1] + 'が入力されました。¥n'
    show_message += "電話番号:" + values[2] + "が入力されました。"
    print(show_message)
    # ポップアップ
    sg.popup(show_message)
    # セクション 4 - ウィンドウの破棄と終了
    window.close()
    28

    View Slide

  29. 基本の形 (2/8)
    1.テーマ
    2.レイアウト
    3.ウィンドウの設定
    4.イベント
    29

    View Slide

  30. 基本の形(テーマ) (3/8)
    # セクション1 - オプションの設定と標準レイアウト
    sg.theme('Dark Blue 3')
    30

    View Slide

  31. 基本の形(レイアウト) (4/8)
    • レイアウトはリストで記載できる
    layout = [
    [sg.Text('Python GUI')],
    [sg.Text('名前', size=(15, 1)), sg.InputText('○○〇×××')],
    [sg.Text('住所', size=(15, 1)), sg.InputText('△△△△村')],
    [sg.Text('電話番号', size=(15, 1)), sg.InputText('xxx-xxx-xxx')],
    [sg.Submit(button_text='実行ボタン')]
    ]
    31

    View Slide

  32. 基本の形(レイアウト)(5/8)
    • リストを入れ子にして作ることも可能
    • 見やすい
    frame1 = sg.Frame('住所', [[sg.Text('郵便番号', size=(15, 1))],
    [sg.InputText(key='-POST-NUM-')],
    [sg.Text('都道府県', size=(15, 1), )],
    [sg.InputText(key='-PREFECTURES-')],
    [sg.Text('住所', size=(15, 1))],
    [sg.InputText(key='-ADDRESS-')],
    ],
    relief=sg.RELIEF_SUNKEN, tooltip='住所をいれてね!')
    layout = [
    [sg.Text('Python GUI')],
    [sg.Text('名前', size=(15, 1)), sg.InputText(
    default_text='○○〇×××', key='-USER-NAME-')],
    [sg.Text('住所を入れてね', size=(15, 1)), frame1], # frame1のレイアウトを入れ
    子にして入れている
    [sg.Text('電話番号', size=(15, 1)), sg.InputText(
    default_text='xxx-xxx-xxx', key='-PHONE-NUM-')],
    [sg.Submit('実行ボタン')]
    ]
    32

    View Slide

  33. 基本の形(ウィンドウの設定)(6/8)
    # セクション 2 - ウィンドウの生成
    window = sg.Window('住所を入力', layout)
    • ウィンドウ、フォントなどのサイズを指定しなくても
    自動でサイズを調整してくれる
    • サイズを指定して変更も可能
    • ウィンドウは透明度の設定も可能
    # セクション 2 - ウィンドウの生成
    window = sg.Window('住所を入力', size=(300, 200))
    33

    View Slide

  34. 基本の形(イベント)(7/8)
    • ボタンのタイトルをイベント名として取得できる
    • 各項目(widget※)の値はリストで取得可能
    ※: GUI を構成するボタンなどの部品
    layout = [
    [sg.Text('Python GUI')],
    [sg.Text('名前', size=(15, 1)), sg.InputText('○○〇×××')],
    [sg.Text('住所', size=(15, 1)), sg.InputText('△△△△村')],
    [sg.Text('電話番号', size=(15, 1)), sg.InputText('xxx-xxx-xxx')],
    [sg.Submit(button_text='実行ボタン')]
    ]
    # セクション 3 - イベントループ
    while True:
    event, values = window.read()
    if event == '実行ボタン':
    show_message = "名前:" + values[0] + 'が入力されました。¥n'
    show_message += "住所:" + values[1] + 'が入力されました。¥n'
    show_message += "電話番号:" + values[2] + "が入力されました。"
    print(show_message)
    # ポップアップ
    sg.popup(show_message)
    34

    View Slide

  35. 基本の形(イベント)(8/8)
    • 各パーツにKeyを設定して、
    Keyを指定して値を取得する
    ことも可能
    frame1 = sg.Frame('住所', [[sg.Text('郵便番号', size=(15, 1))],
    [sg.InputText(key='-POST-NUM-')],
    [sg.Text('都道府県', size=(15, 1), )],
    [sg.InputText(key='-PREFECTURES-')],
    [sg.Text('住所', size=(15, 1))],
    [sg.InputText(key='-ADDRESS-')],
    ],
    relief=sg.RELIEF_SUNKEN, tooltip='住所をいれてね!')
    layout = [
    [sg.Text('Python GUI')],
    [sg.Text('名前', size=(15, 1)), sg.InputText(
    default_text='○○〇×××', key='-USER-NAME-')],
    [sg.Text('住所を入れてね', size=(15, 1)), frame1],
    [sg.Text('電話番号', size=(15, 1)), sg.InputText(
    default_text='xxx-xxx-xxx', key='-PHONE-NUM-')],
    [sg.Submit('実行ボタン')]
    ]
    # セクション 3 - イベントループ
    while True:
    event, values = window.read()
    if event == '実行ボタン':
    print(values)
    show_message = "名前:" + values['-USER-NAME-'] + 'が入力されました。¥n'
    show_message += "郵便番号:" + values['-POST-NUM-'] + 'が入力されました。¥n'
    show_message += "都道府県:" + values['-PREFECTURES-'] + 'が入力されました。¥n'
    show_message += "住所:" + values['-ADDRESS-'] + 'が入力されました。¥n'
    show_message += "電話番号:" + values['-PHONE-NUM-'] + "が入力されました。"
    35
    valuesの中身
    {
    '-USER-NAME-': '○○〇×××’,
    '-POST-NUM-': '210’,
    '-PREFECTURES-': '東京都’,
    '-ADDRESS-': '渋谷区’,
    '-PHONE-NUM-': 'xxx-xxx-xxx’
    }

    View Slide

  36. 答え合わせ
    私はPythonで機械学習がしたい。
    だからGUI(値の入出力、結果表示)は
    こだわらなくてでいい
    ※答えは一例です人の数ほど答えがあります
    PySimpleGUIでGUIを簡単に作ろう!!
    36

    View Slide

  37. exe化(1/2)
    • PyInstllerを使用する
    • 以下のエラーが出た場合は、--hidden-import tkinter をオプション
    に加える
    • PyInstllerを使用したEXE化はオプションがあって色々難しい
    • Onefileにはしない
    • 3rd Party Libraly(PiPでインストールするライブラリー)は最初はアプリに使用し
    ない(importしない)→標準ライブラリのみでアプリを作ってみる
    pip install PyInstaller
    pyinstaller -wF my_program.py
    ValueError: script '.......¥src¥tkinter' not found
    37

    View Slide

  38. exe化(2/2)
    • 公式でPyInstllerを組み合わせたGUIがある
    • PySimpleGUI-exemaker
    • https://github.com/PySimpleGUI/PySimpleGUI/tree/master/exema
    ker
    • 1個のexeファイルになる
    38

    View Slide

  39. お品書き
    1. 一部 PythonのGUIについて
    2. 二部 tkinterについて
    3. 三部 PySimpleGUIについて
    4. 四部 PySimpleGUIのアプリの例
    39

    View Slide

  40. アプリの例(グラフ)
    • PySimpleGUIだけでも簡単なグラフは作れる
    • リアルタイムグラフやアニメーションもできる
    • Matplotlibの連携もできる
    • https://qiita.com/dario_okazaki/items/dc72976987d7ef485df1
    40

    View Slide

  41. アプリの例(グラフ2)
    • 公式のサンプル( https://pysimplegui.trinket.io/demo-
    programs#/graph-element/visualizing-sorts )
    • 棒グラフの値をバブルソートで並べ替えるアニメーションのグラフ
    です 41

    View Slide

  42. アプリの例(グラフ3)
    • 公式のサンプル(https://github.com/PySimpleGUI/PySimpleGUI-
    Rainmeter-CPU-
    Cores/blob/master/PySimpleGUI_Rainmeter_CPU_Cores.py)
    • CPUの値を表示するグラフです。背景が半透明だったりタブを
    非表示にしています
    42

    View Slide

  43. アプリの例(VBAの代わりとして)
    • VBAの代わりとして
    • ファイルダイアログやリスト、ログを出力できる
    • https://qiita.com/dario_okazaki/items/4ba70e8a7ee1a6b024
    e8
    43

    View Slide

  44. アプリの例(画像処理の入力、確認)
    • 「アスキーアートを自動生成する - Pythonでいろいろやってみる」https://tat-pytone.hatenablog.com/entry/2020/02/26/202205
    のコードをお借りしてUIをつけてみました。
    • UIつける作業自体は2時間程度
    • 公式のデモを参考
    https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Img_Viewer.py
    https://github.com/PySimpleGUI/PySimpleGUI-Photo-Colorizer
    44

    View Slide

  45. アプリの例
    • PySimpleGUIには公式でサンプルがたくさんある
    • https://github.com/PySimpleGUI/PySimpleGUI 配下のデモ
    • https://pysimplegui.trinket.io/demo-programs
    • PySimpleGUIのみで作られたものやほかのライブラリを組み合わせた
    ものまで様々
    • OpenCVを使った画像処理や機械学習による物体検出の例もある
    45

    View Slide

  46. おまけ アンドロイドでの実行について
    • Pydroid3で実行できる
    • https://play.google.com/store/apps/details?id=ru.iiec.pydroid3&hl=ja
    • 公式デモ:
    https://github.com/PySimpleGUI/PySimpleGUI/tree/master/DemoPro
    grams/PyDroid3
    46

    View Slide

  47. Macでの動作環境について
    • tkinterを場合によってはインストールする必要あり
    • インストール設定が色々面倒
    • Tkinter自体がMacではIME(全角文字が入力中の時の文字)が出ない
    • PySimpleGUIWx(wxPythonのラッパー)を使用する
    47

    View Slide

  48. GUIを勉強する意味
    • Webだと実際の運用だとインフラの知識が必要
    • GUIだと自分の環境であれば失敗しづらい
    • デモ見せるときに優位
    • オフライン環境、ネットがつながらない環境でも動く
    • パケット気にしない
    48

    View Slide

  49. まとめ
    • PySimpleGUIを使うと簡単にデスクトップアプリが作れる
    • tkinterを直接使うよりも簡単
    • 簡単なグラフだったりVBAの代わりになるものも作れる
    49

    View Slide

  50. 参考:英語のドキュメントの読み方(1/3)
    • PythonのGUIライブラリは日本語の記事が少ないです
    • 公式ドキュメント(英語)を読む
    • 詳しい記事はたいてい英語
    50

    View Slide

  51. 参考:英語のドキュメントの読み方(2/3)
    • 英語と日本語の翻訳(Google翻訳)を並べて読む
    51

    View Slide

  52. 参考:英語のドキュメントの読み方(3/3)
    • 難しい単語は辞書を引く
    • 参考:Chrome拡張の高速な英語辞書ツールをつ
    くりました(Mouse Dictionary)
    • https://qiita.com/wtetsu/items/c43232c6c44918e9
    77c9
    • IT用語など決まった用語には注意する
    • 例:「 separation of concerns」→「関心の分離
    ( SoC )」※機械翻訳だと「懸念の分離」や「関心
    事の分離」と訳されることがある
    52

    View Slide