【Python】PySimpleGUIでログイン仕様のGUIを実装してみる

【Python】PySimpleGUIでログイン仕様のGUIを実装してみる

今回は「PySimpleGUI」というライブラリを使用し、簡単なログイン仕様のGUIを作成してみます。

PySimpleGUIのリファレンスは以下を参照してください。
参考:PySimpleGUI Reference – Home


以下のような環境で動作確認済みです。

  • macOS Big Sur version 11.2.1
  • Python 3.7.2
  • PySimpleGUI 4.29.0

それでは作っていきます。

ログインGUIの仕様

では、GUIを作成する前に、どのような仕様にするのかを簡単に決めておきます。
今回考える機能として、最低限必要なものとしては、

  • ログイン画面には、名前入力欄とパスワード 入力欄とログインボタンがある。
  • ログインボタンを押したとき、名前とパスワードが一致していたら画面遷移(メイン画面に遷移)を行う。
  • メイン画面には、ログアウトボタンがある。
  • メイン画面のログアウトを押したら、「ログアウトしますか?」のダイアログが表示される。
  • 「はい」を選択すると、再度ログイン画面に戻る。

の5つと仮定します。


上のリストをまとめると、このようになります。

注意点として、ログイン内部処理ではDBは用いず、指定した値との一致判定をおこないます。

処理部品としては、以下の4つに大きく分類されます。

  • ログイン画面
  • ログイン判定処理
  • メイン画面
  • 確認ダイアログ

これらを実装していきます。

PySimpleGUIのインストール方法

PySimpleGUIのインストール方法は、コマンドプロンプトやターミナルで以下のコマンドを入力してインストールします。

pip install pysimplegui

上記コマンドでインストールできない方は以下のコードを試してください。

pip3 install pysimplegui

ログイン画面を作成する

それではログイン画面を作成します。
PySimpleGUIリファレンスのJump-Startにあるコードを参考にして、実装していきます。

# -*- coding: utf-8 -*-
import PySimpleGUI as sg # PySimpleGUIをインポート

# TODO 1. チェック判定の関数を作る
# TODO 2. メイン画面を表示する関数を作る

# テーマカラーを設定
sg.theme("SandyBeach") 

# ログイン画面のレイアウト
layout = [
    [sg.Text("ログイン画面")],
    [sg.Text("名前:", size=(10, 1)), sg.Input("", size=(25, 1), key="-name-")],
    [sg.Text("パスワード:", size=(10, 1)), sg.Input("", size=(25, 1), key="-password-")],
    [sg.Button("ログイン", size=(10, 1), enable_events=True, key="-login-")]
]

window = sg.Window("ログイン画面", layout, size=(400, 400))

while True:
    # イベントとGUI要素の値を取得する
    event, values = window.read()

    # ×ボタンが押された時はループを抜け出す。
    if event == sg.WIN_CLOSED or event == 'Exit':
        break

    # ログインボタンが押された場合の処理
    elif event == "-login-":
        # TODO 3. データが一致したら、メイン画面を表示する処理を実装
        pass

# windowを終了させる
window.close()

このコードを実行すると、次のような画面が生成されます。

以降は、TODOのコメント直下に必要な機能を実装していきます。

ログイン判定処理を作成する

コード内コメント「# TODO 1. チェック判定の関数を作る 」の下にログイン判定関数を作成していきます。

# TODO 1. チェック判定の関数を作る

def check_data(name: str, password: str) -> bool:
    """
    ログイン名とパスワードが、指定された値と合致しているか判定する関数

    Args:
        name (str): 入力された名前
        password (str): 入力されたパスワード

    Returns:
        bool: 判定結果
    """
    # 正しいデータ
    correct_data = ("TERU", "TERU_PASSWORD")

    if (name, password) == correct_data:
        return True
    return False

正しいデータの名前とパスワードは、[TERU]と[TERU_PASSWORD]にしました。
もし、正しいデータと形があっていたら[True]を、それ以外はFalseを返します。

[name: str]や[-> bool]などの型判定に関しては、次節で説明します。

メイン画面とログアウト確認ダイアログを作成する

コード内コメント「# TODO 2. メイン画面を表示する関数を作る 」の下に作成していきます。
メイン画面では、ログアウト判定をするために返り値を利用したいので関数で実装していきます。

# TODO 2. メイン画面を表示する関数を作る

from typing import Optional  # 型推定に用いる
def display_main() -> Optional[bool]:
    """
    メイン画面を表示する関数

    Returns:
        Optional[bool]: ログアウト判定 True or None
                        Noneならログイン画面も終了させる。
    """

    main_layout = [
        [sg.Text("メイン画面")],
        [sg.Text("ようこそ メイン画面へ")],
        [sg.Button("ログアウト", size=(10, 1), enable_events=True, key="-logout-")]
    ]

    main_window = sg.Window("メイン画面", main_layout, size=(400, 400))
    ret = None # 返り値

    while True:
        # イベントとGUI要素の値を取得する
        event, values = main_window.read()
        if event == sg.WIN_CLOSED or event == 'Exit':
            break

        # ログインボタンが押されたら
        elif event == "-logout-":
            # データが一致したら、メイン画面を表示する処理
            logout_ret = sg.PopupOKCancel("ログアウトしますか?", title="ログアウト確認", keep_on_top=True)

            # もしもOKならTrueを返し、メイン画面を終了する。
            if logout_ret == "OK":
                ret = True
                break
            else:
                continue

    # メイン画面を終了する
    main_window.close()
    # 最後に返り値を渡す
    return ret

この関数を実行すると以下のような画面が生成されます。


ログアウト確認ダイアログは、PySimpleGUIで簡単にできるポップアップで実装しています。
logout_retの返り値は[OK], [Cancel], [None]のいずれかが返されます。

logout_ret = sg.PopupOKCancel("ログアウトしますか?", title="ログアウト確認", keep_on_top=True)
# もしもOKならTrueを返し、メイン画面を終了する。
if logout_ret == "OK":
    ret = True
        break
    else:
        continue
[OK]が押されたらメイン画面を終了させ、[Cancel], [None]の場合はそのままメイン画面を表示します。


メイン画面の終了条件としては、「ログアウトを行う」もしくは「×ボタンを押してメイン画面を終了させる」ことです。

ログアウトの場合は[True]を、強制終了の場合は[None]を返します。
次節で実装するコードではこの返り値を利用します。



前節と今節で[str]や[Optional]などを使用しました。これは型推定を行なってくれるもので、今回の例で言うと[bool型もしくはNoneが返り値とする]という意味です。

もちろん、この表示の仕方をしなくても実行可能です。
型推定に関して、詳しくは下記リンクを参照してください。

参考:Pythonではじまる、型のある世界 – Qiita

ログイン判定してメイン画面を表示させる

コード内コメント「# TODO 3. データが一致したら、メイン画面を表示する処理を実装」の下に作成していきます。

# データが一致したら、メイン画面を表示する
if check_data(name=values["-name-"], password=values["-password-"]):
    window.Hide() # ログイン画面を隠す
    # メイン画面を表示する
    main_return = display_main()
    # もしNoneが返ってきたらログイン画面も終了させる
    if main_return is None:
        break
    window.UnHide() # ログイン画面を再表示する

window.Hide()とUnHideを使用するとGUIを表示・非表示にすることができます。
名前とパスワードが一致していたらログイン画面を隠し、display_main関数からメイン画面を表示します。
メイン画面表示後の返り値がNoneなら、ログイン画面も終了させています。

これで全部品が完成しました。

全体のコード

全体のコードはこのようになります。

# -*- coding: utf-8 -*-
import PySimpleGUI as sg # PySimpleGUIをインポート
from typing import Optional  # 型推定に用いる

# TODO 1. チェック判定の関数を作る
def check_data(name: str, password: str) -> bool:
    """
    ログイン名とパスワードが、指定された値と合致しているか判定する関数

    Args:
        name (str): 入力された名前
        password (str): 入力されたパスワード

    Returns:
        bool: 判定結果
    """
    # 正しいデータ
    correct_data = ("TERU", "TERU_PASSWORD")

    if (name, password) == correct_data:
        return True
    return False

# TODO 2. メイン画面を表示する関数を作る
def display_main() -> Optional[bool]:
    """
    メイン画面を表示する関数

    Returns:
        Optional[bool]: ログアウト判定 True or None
                        Noneならログイン画面も終了させる。
    """

    main_layout = [
        [sg.Text("メイン画面")],
        [sg.Text("ようこそ メイン画面へ")],
        [sg.Button("ログアウト", size=(10, 1), enable_events=True, key="-logout-")]
    ]

    main_window = sg.Window("メイン画面", main_layout, size=(400, 400))
    ret = None # 返り値

    while True:
        # イベントとGUI要素の値を取得する
        event, values = main_window.read()
        if event == sg.WIN_CLOSED or event == 'Exit':
            break

        # ログインボタンが押されたら
        elif event == "-logout-":
            # データが一致したら、メイン画面を表示する処理
            logout_ret = sg.PopupOKCancel("ログアウトしますか?", title="ログアウト確認", keep_on_top=True)

            # もしもOKならTrueを返し、メイン画面を終了する。
            if logout_ret == "OK":
                ret = True
                break
            else:
                continue

    # メイン画面を終了する
    main_window.close()
    # 最後に返り値を渡す
    return ret


# テーマカラーを設定
sg.theme("SandyBeach")

# ログイン画面のレイアウト
layout = [
    [sg.Text("ログイン画面")],
    [sg.Text("名前:", size=(10, 1)), sg.Input("", size=(25, 1), key="-name-")],
    [sg.Text("パスワード:", size=(10, 1)), sg.Input("", size=(25, 1), key="-password-")],
    [sg.Button("ログイン", size=(10, 1), enable_events=True, key="-login-")]
]

window = sg.Window("ログイン画面", layout, size=(400, 400))

while True:
    # イベントとGUI要素の値を取得する
    event, values = window.read()

    # ×ボタンが押された時はループを抜け出す。
    if event == sg.WIN_CLOSED or event == 'Exit':
        break

    # ログインボタンが押された場合の処理
    elif event == "-login-":
        # TODO 3. データが一致したら、メイン画面を表示する処理を実装
        if check_data(name=values["-name-"], password=values["-password-"]):
            window.Hide() # ログイン画面を隠す
            # メイン画面を表示する
            main_return = display_main()
            # もしNoneが返ってきたらログイン画面も終了させる
            if main_return is None:
                break
            window.UnHide() # ログイン画面を再表示する
# windowを終了させる
window.close()

まとめ

今回は簡単なログイン仕様GUIを実装しました。

要素の中心寄せやフレーム等の細かな設定を行っていない為、簡素な感じになってしまいましたね…笑

他にも機能としてパスワードを伏字にしたり、DBを利用してアカウント登録ができたりすると、充実したログイン画面GUIが作れるのではないでしょうか?


皆さんも、ぜひ自分だけのGUIを作ってみてください。


PySimpleGUIカテゴリの最新記事

%d人のブロガーが「いいね」をつけました。