Share
Embed
Pythonでデスクトップアプリを簡単に作る方法
PyCon mini Shizuoka で発表する内容のスライドです。
PythonのGUIライブラリPySimpleGUIを使用してデスクトップアプリを作成する方法を紹介します
https://shizuoka.pycon.jp/session/dario_okazaki/
code: https://github.com/okajun35/for_pycon_shizu
dario okazaki
February 29, 2020
Transcript
52 slides
-
お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて
4. 四部 PySimpleGUIのアプリの例 2 -
自己紹介 • オカザキ(@dario_okazaki) • 所属:(株)スカラコミュニケーション ズ • 職業:サーバーサイドエンジニア • PyconJP2017
トーク「Kivyによるアプ リケーション開発のすすめ」 • 長野Python会 with NSEG(2018/7/28) 「PythonのGUI@2018」 3 -
会社紹介 • 株式会社スカラコミュニケーションズ • https://scala-com.jp/ • BtoB向けのシステム開発 • メインの開発はPHP, •
Python,C#でも開発 • 所在地:渋谷ヒカリエ(1月~) • エンジニア募集中 4 -
お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて
4. 四部 PySimpleGUIのアプリの例 8 -
PythonでのGUIの立ち位置(2/2) JET BRAINSのThe State of Developer Ecosystem 2019のPythonより 10 •
Pythonを使う上ではメジャーではない -
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はライブラリではなくて手法です -
PythonのGUIについて(2/3) 12 • cefpython • PyGObject • Pyglet • PyGUI
• libavg • Pyforms etc・・・ -
PythonのGUIについて(3/3) • その他(Android端末で動くもの) • QPython ※Andoridで動くIDE • Pydroid3 ※Andoridで動くIDE •
LINE MessageAPI※Lineアプリ上で動くもの • IOSだとPythonistaというアプリがある 13 -
お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて
4. 四部 PySimpleGUIのアプリの例 17 -
tkinterについて(1/3) • Pythonの標準GUI • 環境構築が不要 • Pythonのインストール時に一緒にインストールされる • 公式リファレンスにドキュメントがある •
Tk を用いたグラフィカルユーザインターフェイス 18 -
tkinterについて(3/3) パーソナルコンピュータの基本ソフトウェアとウィンドウ環境としては Windows, macOS, Linux/X-Window など複数のものが使われており、それぞれにウィンドウ の 描画などは異なった方法で行われます。これらの OS/ウィンドウ環境の差異を 吸収
し、共通に使える GUI 用のフレームワークとして Tcl/Tk があります。 tkinter はこの Tcl/Tk を Python から利用できるようにしたパッケージです 20 ~ 京都大学 プログラミング演習 Python 2019 Version2020_02_13_01.pdf から引用 ~ -
GUIの基本 GUI 型のアプリケーションでは、メニューやボタンなどによるさ まざまな操作を ユーザ自身が選択して利用します。そして、操作 に対してコンピュータが適切に応 答することを期待します。 このようなユーザの操作を「イベント」と呼びます。多くの GUI 型のアプリケーションは
GUI 用の「フレームワーク」を利用しま す。 フレームワークはマウスやキーボードの操作を監視してイベントを 検出し、プロ グラマーによって設定されたイベント処理用のプロ グラムを呼び出します。 フレームワークを用いた GUI 型のアプリ ケーションではプログラマーは主として 以下のような部分のプロ グラミングを担います。 イベントが発生した際に行う処理の定義 このようなプログラミン グをイベントに対する応答を主に記述することからイベン ト駆動 型 (event-driven) プログラミングと呼びます。 21 ~ 京都大学 プログラミング演習 Python 2019 Version2020_02_13_01.pdf から引用 ~ -
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 -
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 -
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 -
お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて
4. 四部 PySimpleGUIのアプリの例 25 -
PySimpleGUIの紹介 • https://pysimplegui.readthedocs.io/en/latest/ • 2018年にできたライブラリー • TkinterのラッパーでPythonライクに書けるのが特徴 • 派生でwxPython、PyQtのラッパーライブラリーも存在 •
公式では元のライブラリで書くのに比べてコード量が1/2~1/10になると説明 • Githubでは3,000スター • ライセンスはLGPL-3.0 26 -
基本の形 (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 -
基本の形(レイアウト) (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 -
基本の形(レイアウト)(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 -
基本の形(ウィンドウの設定)(6/8) # セクション 2 - ウィンドウの生成 window = sg.Window('住所を入力', layout)
• ウィンドウ、フォントなどのサイズを指定しなくても 自動でサイズを調整してくれる • サイズを指定して変更も可能 • ウィンドウは透明度の設定も可能 # セクション 2 - ウィンドウの生成 window = sg.Window('住所を入力', size=(300, 200)) 33 -
基本の形(イベント)(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 -
基本の形(イベント)(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’ } -
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 -
お品書き 1. 一部 PythonのGUIについて 2. 二部 tkinterについて 3. 三部 PySimpleGUIについて
4. 四部 PySimpleGUIのアプリの例 39 -
アプリの例(画像処理の入力、確認) • 「アスキーアートを自動生成する - 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 -
アプリの例 • PySimpleGUIには公式でサンプルがたくさんある • https://github.com/PySimpleGUI/PySimpleGUI 配下のデモ • https://pysimplegui.trinket.io/demo-programs • PySimpleGUIのみで作られたものやほかのライブラリを組み合わせた
ものまで様々 • OpenCVを使った画像処理や機械学習による物体検出の例もある 45 -
参考:英語のドキュメントの読み方(3/3) • 難しい単語は辞書を引く • 参考:Chrome拡張の高速な英語辞書ツールをつ くりました(Mouse Dictionary) • https://qiita.com/wtetsu/items/c43232c6c44918e9 77c9
• IT用語など決まった用語には注意する • 例:「 separation of concerns」→「関心の分離 ( SoC )」※機械翻訳だと「懸念の分離」や「関心 事の分離」と訳されることがある 52