Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for Jun okazaki 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

Avatar for Jun okazaki

Jun okazaki

February 29, 2020

More Decks by Jun okazaki

Other Decks in Technology

Transcript

  1. 自己紹介 • オカザキ(@dario_okazaki) • 所属:(株)スカラコミュニケーション ズ • 職業:サーバーサイドエンジニア • PyconJP2017

    トーク「Kivyによるアプ リケーション開発のすすめ」 • 長野Python会 with NSEG(2018/7/28) 「PythonのGUI@2018」 3
  2. 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はライブラリではなくて手法です
  3. PythonのGUIについて(3/3) • その他(Android端末で動くもの) • QPython ※Andoridで動くIDE • Pydroid3 ※Andoridで動くIDE •

    LINE MessageAPI※Lineアプリ上で動くもの • IOSだとPythonistaというアプリがある 13
  4. tkinterについて(3/3) パーソナルコンピュータの基本ソフトウェアとウィンドウ環境としては Windows, macOS, Linux/X-Window など複数のものが使われており、それぞれにウィンドウ の 描画などは異なった方法で行われます。これらの OS/ウィンドウ環境の差異を 吸収

    し、共通に使える GUI 用のフレームワークとして Tcl/Tk があります。 tkinter はこの Tcl/Tk を Python から利用できるようにしたパッケージです 20 ~ 京都大学 プログラミング演習 Python 2019 Version2020_02_13_01.pdf から引用 ~
  5. GUIの基本 GUI 型のアプリケーションでは、メニューやボタンなどによるさ まざまな操作を ユーザ自身が選択して利用します。そして、操作 に対してコンピュータが適切に応 答することを期待します。 このようなユーザの操作を「イベント」と呼びます。多くの GUI 型のアプリケーションは

    GUI 用の「フレームワーク」を利用しま す。 フレームワークはマウスやキーボードの操作を監視してイベントを 検出し、プロ グラマーによって設定されたイベント処理用のプロ グラムを呼び出します。 フレームワークを用いた GUI 型のアプリ ケーションではプログラマーは主として 以下のような部分のプロ グラミングを担います。 イベントが発生した際に行う処理の定義 このようなプログラミン グをイベントに対する応答を主に記述することからイベン ト駆動 型 (event-driven) プログラミングと呼びます。 21 ~ 京都大学 プログラミング演習 Python 2019 Version2020_02_13_01.pdf から引用 ~
  6. 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
  7. 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
  8. 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
  9. 基本の形 (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
  10. 基本の形(レイアウト) (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
  11. 基本の形(レイアウト)(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
  12. 基本の形(ウィンドウの設定)(6/8) # セクション 2 - ウィンドウの生成 window = sg.Window('住所を入力', layout)

    • ウィンドウ、フォントなどのサイズを指定しなくても 自動でサイズを調整してくれる • サイズを指定して変更も可能 • ウィンドウは透明度の設定も可能 # セクション 2 - ウィンドウの生成 window = sg.Window('住所を入力', size=(300, 200)) 33
  13. 基本の形(イベント)(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
  14. 基本の形(イベント)(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’ }
  15. 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
  16. 参考:英語のドキュメントの読み方(3/3) • 難しい単語は辞書を引く • 参考:Chrome拡張の高速な英語辞書ツールをつ くりました(Mouse Dictionary) • https://qiita.com/wtetsu/items/c43232c6c44918e9 77c9

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