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

Fed4c6cfec7502b771e12f08f8d5ec6d?s=47 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

Fed4c6cfec7502b771e12f08f8d5ec6d?s=128

Jun okazaki

February 29, 2020
Tweet

Transcript

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

  2. お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて

    4. 四部 PySimpleGUIのアプリの例 2
  3. 自己紹介 • オカザキ(@dario_okazaki) • 所属:(株)スカラコミュニケーション ズ • 職業:サーバーサイドエンジニア • PyconJP2017

    トーク「Kivyによるアプ リケーション開発のすすめ」 • 長野Python会 with NSEG(2018/7/28) 「PythonのGUI@2018」 3
  4. 会社紹介 • 株式会社スカラコミュニケーションズ • https://scala-com.jp/ • BtoB向けのシステム開発 • メインの開発はPHP, •

    Python,C#でも開発 • 所在地:渋谷ヒカリエ(1月~) • エンジニア募集中 4
  5. 問題提起 私はPythonで◦◦◦がしたい。 だから◦◦◦は◦◦◦でいい 5

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

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

  8. お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて

    4. 四部 PySimpleGUIのアプリの例 8
  9. PythonでのGUIの立ち位置(1/2) 9 JET BRAINSのThe State of Developer Ecosystem 2019のPythonより

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

    Pythonを使う上ではメジャーではない
  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はライブラリではなくて手法です
  12. PythonのGUIについて(2/3) 12 • cefpython • PyGObject • Pyglet • PyGUI

    • libavg • Pyforms etc・・・
  13. PythonのGUIについて(3/3) • その他(Android端末で動くもの) • QPython ※Andoridで動くIDE • Pydroid3 ※Andoridで動くIDE •

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

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

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

  17. お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて

    4. 四部 PySimpleGUIのアプリの例 17
  18. tkinterについて(1/3) • Pythonの標準GUI • 環境構築が不要 • Pythonのインストール時に一緒にインストールされる • 公式リファレンスにドキュメントがある •

    Tk を用いたグラフィカルユーザインターフェイス 18
  19. tkinterについて(2/3) • Pythonの標準IDEである「IDLE」にも使われている • Tcl/TkのTk部分を移植している • Tcl/TK自体は初リリースは1998年! 19

  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 から引用 ~
  21. GUIの基本 GUI 型のアプリケーションでは、メニューやボタンなどによるさ まざまな操作を ユーザ自身が選択して利用します。そして、操作 に対してコンピュータが適切に応 答することを期待します。 このようなユーザの操作を「イベント」と呼びます。多くの GUI 型のアプリケーションは

    GUI 用の「フレームワーク」を利用しま す。 フレームワークはマウスやキーボードの操作を監視してイベントを 検出し、プロ グラマーによって設定されたイベント処理用のプロ グラムを呼び出します。 フレームワークを用いた GUI 型のアプリ ケーションではプログラマーは主として 以下のような部分のプロ グラミングを担います。 イベントが発生した際に行う処理の定義 このようなプログラミン グをイベントに対する応答を主に記述することからイベン ト駆動 型 (event-driven) プログラミングと呼びます。 21 ~ 京都大学 プログラミング演習 Python 2019 Version2020_02_13_01.pdf から引用 ~
  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
  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
  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
  25. お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて

    4. 四部 PySimpleGUIのアプリの例 25
  26. PySimpleGUIの紹介 • https://pysimplegui.readthedocs.io/en/latest/ • 2018年にできたライブラリー • TkinterのラッパーでPythonライクに書けるのが特徴 • 派生でwxPython、PyQtのラッパーライブラリーも存在 •

    公式では元のライブラリで書くのに比べてコード量が1/2~1/10になると説明 • Githubでは3,000スター • ライセンスはLGPL-3.0 26
  27. インストール • Pure Pythonなのでインストールは簡単 pip install pysimplegui or pip3 install

    pysimplegui 27
  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
  29. 基本の形 (2/8) 1.テーマ 2.レイアウト 3.ウィンドウの設定 4.イベント 29

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

  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
  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
  33. 基本の形(ウィンドウの設定)(6/8) # セクション 2 - ウィンドウの生成 window = sg.Window('住所を入力', layout)

    • ウィンドウ、フォントなどのサイズを指定しなくても 自動でサイズを調整してくれる • サイズを指定して変更も可能 • ウィンドウは透明度の設定も可能 # セクション 2 - ウィンドウの生成 window = sg.Window('住所を入力', size=(300, 200)) 33
  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
  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’ }
  36. 答え合わせ 私はPythonで機械学習がしたい。 だからGUI(値の入出力、結果表示)は こだわらなくてでいい ※答えは一例です人の数ほど答えがあります PySimpleGUIでGUIを簡単に作ろう!! 36

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

    38
  39. お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて

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

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

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

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

  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
  45. アプリの例 • PySimpleGUIには公式でサンプルがたくさんある • https://github.com/PySimpleGUI/PySimpleGUI 配下のデモ • https://pysimplegui.trinket.io/demo-programs • PySimpleGUIのみで作られたものやほかのライブラリを組み合わせた

    ものまで様々 • OpenCVを使った画像処理や機械学習による物体検出の例もある 45
  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
  47. Macでの動作環境について • tkinterを場合によってはインストールする必要あり • インストール設定が色々面倒 • Tkinter自体がMacではIME(全角文字が入力中の時の文字)が出ない • PySimpleGUIWx(wxPythonのラッパー)を使用する 47

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

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

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

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

  52. 参考:英語のドキュメントの読み方(3/3) • 難しい単語は辞書を引く • 参考:Chrome拡張の高速な英語辞書ツールをつ くりました(Mouse Dictionary) • https://qiita.com/wtetsu/items/c43232c6c44918e9 77c9

    • IT用語など決まった用語には注意する • 例:「 separation of concerns」→「関心の分離 ( SoC )」※機械翻訳だと「懸念の分離」や「関心 事の分離」と訳されることがある 52