PySimpleGUIでQRコード作成GUIを作る

##はじめに

Pythonコミニティー「みんなのPython勉強会」の発表で、PySimpleGUIの紹介があった。
[PythonのスクリプトにGUIをつける方法](https://speakerdeck.com/okajun35/pythonfalsesukuriputoniguiwotukerufang-fa)
これまで、何とかGUIをTKを使って（あまりちゃんと理解せず）に作っていました。私にとっては、このライブラリーはとても分かりやすいものでした。
試しに使ってみたくなったので、例題としてQRコードを作成するGUIを作ってみました。

PySimpleGUIの説明は、こちらを参照してください。
[Tkinterを使うのであればPySimpleGUIを使ってみたらという話](https://qiita.com/dario_okazaki/items/656de21cab5c81cabe59)
[Pythonでデスクトップアプリを簡単に作る方法](https://speakerdeck.com/okajun35/pythondedesukutotupuapuriwojian-dan-nizuo-rufang-fa)
[PySimpleGUI](https://pysimplegui.readthedocs.io/en/latest/)

##環境
Win10Pro
Anaconda
Python3.7

インストールモジュール
qrcode　<--QRコード作成モジュール、PILベース
PySimpleGUI

公式では、pipでのインストールが書いてありますが、
両モジュールともにcondaでインストールできます。
（condaでは、なるべくpipでインストールしない方が良いため。）

```python
conda install -c conda-forge qrcode pysimplegui
```
## QRコード作成GUIその1

pysimpleguiのImage関数の内容をアップデートしてQRを表示するやり方。

```python
import PySimpleGUI as sg
import qrcode  as qr

sg.theme('Light Blue 2')

def qrmaker(code):
    qr_img = qr.make(str(code))
    qr_img.save('temp.png',format="png")

    return qr_img


image_init = r'./logo.png' #<--動かすときはこのコードの下にある画像をこの名前で保存してください。

layout = [[sg.Text('Data', size=(8, 1)),sg.Input(key='-qr_data-')],
          [sg.Submit()],
          [sg.Text('Save Name', size=(8, 1)),sg.Input(key='-qr_name-')],
          [sg.Button('Save'), sg.Cancel()],
          [sg.Image(image_init,key='-qrimg-')]
          ]

window = sg.Window('QR code', layout)

while True:
    event, values = window.read()
    # None -> Windowが閉じられているかどうか
    # if event is None or event == 'Cancel':　と下のj条件文は同じ 
    if event in (None, 'Cancel'):
        break
    elif event in 'Submit':
        print('QR code Text: {}'.format(values['-qr_data-']))
        qr_img= qrmaker(values['-qr_data-'])
        #sg.Imageのアップデートで表示する。
        #update()の中は、ファイル名でないとエラーになったので、tempという名のファイルを作成しています。
        window['-qrimg-'].update('temp.png')
       
    elif event in 'Save':
        save_qr_name= '{}.png'.format(values['-qr_name-'])
        qr_img = qrmaker(values['-qr_data-'])
        qr_img.save(save_qr_name)
        
window.close()
```
上のコードを動かく時は下の画像を'logo.png'として保存して、プログラムと同じホルダーに入れてください。
![logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/5b3a9cb0-b821-66b5-1327-f6d9fc9305cc.png)

コードを実行すると
![qr1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/f33870f0-5d6c-784b-0090-4912c013c718.jpeg)
DataとSave Nameを入力してSubmitを押すと
![qr2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/0e8cb550-28e0-09de-8b6b-7c5ccbdcdb09.jpeg)

##QRコード作成GUIその2
canvasにQRのイメージを表示させる方法。

```Python
import PySimpleGUI as sg
import qrcode  as qr
from PIL import Image, ImageTk

sg.theme('Light Blue 2')

def qrmaker(code):
    qr_img = qr.make(str(code))

    # qr_img.save('temp.png',format="png")

    return qr_img


image_init = r'./logo.png'
CANVAS_X = 300
CANVAS_Y = 300

layout = [[sg.Text('Data', size=(8, 1)),sg.Input(key='-qr_data-')],
          [sg.Submit()],
          [sg.Text('Save Name', size=(8, 1)),sg.Input(key='-qr_name-')],
          [sg.Button('Save'), sg.Cancel()],
          [sg.Canvas(size=(CANVAS_X, CANVAS_Y), background_color='white', key= '-canvas-')],
          ]

window = sg.Window('QR code', layout)
canvas = window['-canvas-']

while True:
    event, values = window.read()
    if event in (None, 'Cancel'):
        break
    elif event in 'Submit':
        print('QR code Text: {}'.format(values['-qr_data-']))
        qr_img = qrmaker(values['-qr_data-'])
        #TKのCanvasと同じ。PILのイメージをTKに変換しています。
        image_tk = ImageTk.PhotoImage(qr_img)
        canvas.TKCanvas.create_image(CANVAS_X / 2, CANVAS_Y / 2, image=image_tk)
        
    elif event in 'Save':
        save_qr_name= '{}.png'.format(values['-qr_name-'])
        qr_img = qrmaker(values['-qr_data-'])
        qr_img.save(save_qr_name)
        
window.close()
```
![qr3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/2c92a701-91b8-31c7-4dde-dcf4d862cd43.jpeg)
![qr4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165987/ead9419a-557a-2dba-1e6c-6e008799d693.jpeg)

##TKで書いた場合（参考）

```python

import tkinter as tk
import tkinter.filedialog as fd
from PIL import ImageTk

import qrcode  as qr

base = tk.Tk()
base.title('QRcode Generator')
input_area = tk.Frame(base, relief=tk.RAISED, bd=2)
image_area = tk.Frame(base, relief=tk.SUNKEN, bd=2)

# qrcodeにする文字列を保持する変数
encode_text = tk.StringVar()
entry = tk.Entry(input_area, textvariable=encode_text).pack(side=tk.LEFT)

# qr_codeを表示するためのlabel
qr_label = tk.Label(image_area)

def qr_generate():
    qr_label.qr_img = qr.make(encode_text.get())
    img_width, img_height = qr_label.qr_img.size

    # ImageTkフォーマットへ変換
    qr_label.tk_img = ImageTk.PhotoImage(qr_label.qr_img)

    qr_label.config(image=qr_label.tk_img, width=img_width, height=img_height)
    qr_label.pack()

# qrcodeを生成する処理を呼ぶボタン
encode_button = tk.Button(input_area, text='QRcode!', command=qr_generate).pack(side=tk.LEFT)

# フレームを描画
input_area.pack(pady=5)
image_area.pack(padx=3, pady=1)

# 保存メニュー
def save():
    filename = fd.asksaveasfilename(title='名前をつけて保存する', initialfile='qrcode.png')
    if filename and hasattr(qr_label, 'qr_img'):
        qr_label.qr_img.save(filename)

# 終了メニュー
def exit():
    base.destroy()


# メニュー画面作成
menubar = tk.Menu(base)
filemenu = tk.Menu(menubar)
menubar.add_cascade(label='File', menu=filemenu)
filemenu.add_command(label='save', command=save)
filemenu.add_separator()
filemenu.add_command(label='exit', command=exit)
base.config(menu=menubar)

base.mainloop()
```

##まとめ
このモジュールを使えば本当にGUIが簡単に作れます。
デモプログラムもいろいろと掲載されているので、組み合わせて簡単なGUIを作ってみるのもよいと思います。
[PySimpleGUI/DemoPrograms](https://github.com/PySimpleGUI/PySimpleGUI/tree/master/DemoPrograms)