今回は、ログインフォームで実装されていることが多い「パスワードを表示・非表示を切り替えるボタン」をPySimpleGUIで作成したいと思います。
パスワードを表示・非表示を切り替えるボタンは、「PySimpleGUIでログイン仕様のGUIを実装してみる」の記事で作成したログイン仕様GUIのコードに追加していきます。
それでは、まずはどのようなものを作成するのか、実際に使用されている具体例を見てみましょう。
以下の2枚の画像は、Googleアカウントを追加する時の「パスワード入力画面」です。
「パスワードを表示します」にチェックを入れると、パスワードの表示・非表示が入れ替わっています。
パスワード入力ボックスの下にある「Show password」の部分が「パスワードを表示・非表示を切り替えるボタン」です。
このような、押すたびにON/OFFと切り替わるボタンのことを「トグルボタン(toggle button)」と言います。
それではこちらのボタンを実装していきます。
パスワードの非表示方法
それでは、前回使用したコードの「パスワード入力欄」にて、入力した文字をすべて「*」となるように非表示にします。
前回のコードにおいてパスワードのレイアウト部分を、afterのコードのように変更してください。
# ログイン画面のレイアウト 3行目を以下のように変更
# -----------------------------------------------------
# before そのまま表示している
[sg.Text("パスワード:", size=(10, 1)), sg.Input("", size=(25, 1), key="-password-")],
# after 入力された部分を非表示化する
[sg.Text("パスワード:", size=(10, 1)), sg.Input("", size=(25, 1), password_char="*", key="-password-")],
sg.Input() の引数に password_char=”*” を追加しました。
password_charの文字をアスタリスク[*]に設定しているので、パスワードテキストを入力すると全てアスタリスクの伏字で表示されます。
変更したコードを実行すると、以下のようにパスワードが非表示になっています。
こちらのpassword_charの文字はスペース[ ]や、クエスチョンマーク[?]など、他の文字にも変更できるため、好みの文字でパスワードを非表示してみてください。
パスワードを表示・非表示するトグルボタンを作成
次に、パスワードの表示・非表示を行うトグルボタンを作成します。
先ほど見たGoogleの画面のように、チェックボックスで実装します。
ログインGUIのレイアウト部分を以下のように変更します。
# before
layout = [
[sg.Text("ログイン画面")],
...
[sg.Text("パスワード:", size=(10, 1)), sg.Input("", size=(25, 1), key="-password-")],
[sg.Button("ログイン", size=(10, 1), enable_events=True, key="-login-")]
]
# after
layout = [
[sg.Text("ログイン画面")],
...
[sg.Text("パスワード:", size=(10, 1)), sg.Input("", size=(25, 1), password_char="*", key="-password-")],
# 以下の1行を新たに追加
[sg.Checkbox("パスワードを表示します", enable_events=True, key="-toggle_password-")],
[sg.Button("ログイン", size=(10, 1), enable_events=True, key="-login-")]
]
4行目に、チェックボックス要素であるsg.Checkbox(“パスワードを表示します”, enable_events=True, key=”-toggle_password-“)を追加しました。
enable_eventとは、「何かしらのアクションが起きた時に、イベントを発生させる」という意味です。デフォルトでは enable_event=False となっています。
チェックボタンが押されたかどうかで、パスワードの表示判定を行いたいので、今回は enable_event=True と設定します。
こちらを実行すると、チェックボックスが追加されたログイン画面が表示されます。
こちらのボタンを押しても、イベントを追加していないためパスワードの表示・非表示はできません。
それでは次にパスワードを表示・非表示する部分を実装します。
チェックボックスを押してパスワードを表示・非表示を行う
追記:
2021年3月3日に、PySimpleGUI 4.35.0にアップデートされました。
これによって、4.35.0以降でのパスワードの表示・非表示する方法と、それ以前のバージョンで異なる方法になりました。
ご自身のPySimpleGUIのバージョンに合った方法をご覧くださいますようお願いします。
【ver4.35.0以降】パスワードを表示・非表示の方法
ver4.35.0以降では、updateメソッドを使用する事でpassword_charを変更することができるようになりました。
while文のイベント部分に、以下のコードを追加するだけです。
elif event == "-login-":
...
elif event == "-toggle_password-":
# チェックボタンがONだったらパスワードを表示する
if values["-toggle_password-"]:
window["-password-"].update(password_char="")
# チェックボタンがOFFだったらパスワードを非表示にする
else:
window["-password-"].update(password_char="*")
Inputの要素に対して、updateメソッドを使用してpassword_charの文字を変更しています。
こちらを追加してプログラムを実行すると、きちんとパスワードの表示・非表示をすることができました。
これで思惑通り、ボタンを押してパスワードの表示・非表示を実装することができました。
【ver4.35.0以前】パスワードを表示・非表示の方法
パスワードを非表示にするのは簡単ですが、表示に変更するとなると、PySimpleGUIの中にある「Tkinterをいじる」必要があります。
手順としてはこのように行います。
- パスワードの入力欄の要素を指定する。
- 要素の元であるTKEntryを指定する。
- TKEntryのconfigメソッドでpassword_charの元であるshowを空白に更新する。
PySimpleGUIのリファレンス【PySimpleGUI Reference – Home】にはそのような記載がなく、実際にPySimpleGUIのコードを読まないと表示機能を実装することができませんでした。
少し難しい話をしましたが、コードにすると簡単です。
「パスワードを表示します」のボタンが押された時のイベントを、ログインイベントの処理の下に追加します。
elif event == "-login-":
...
elif event == "-toggle_password-":
# チェックボタンがONだったらパスワードを表示する
if values["-toggle_password-"]:
window["-password-"].TKEntry.config(show="")
# チェックボタンがOFFだったらパスワードを非表示にする
else:
window["-password-"].TKEntry.config(show="*")
以下の3つで、パスワードを表示・非表示するトグルボタンを作成できました。
最終プログラムコード
最終的な実行プログラムのコードはこのようになりました。
2021年2月14日時点で、以下の環境で動作済みです。
- macOS Big Sur version 11.2.1
- Python 3.7.2
- PySimpleGUI 4.29.0
こちらのコードをPySimpleGUI 4.35.0 以降で動作させたい場合は、[# 4.35.0以降] とコメントしているコードを用いて実行してください。
# -*- coding: utf-8 -*-
import PySimpleGUI as sg # PySimpleGUIをインポート
from typing import Optional # 型推定に用いる
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
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-")]
]
# windowを宣言
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), password_char="*", key="-password-")],
[sg.Checkbox("パスワードを表示します", enable_events=True, key="-toggle_password-")],
[sg.Button("ログイン", size=(10, 1), enable_events=True, key="-login-")]
]
# windowを宣言
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-":
# データが一致したら、メイン画面を表示する処理
if check_data(name=values["-name-"], password=values["-password-"]):
window.Hide() # ログイン画面を隠す
# メイン画面を表示する
main_return = display_main()
# もしNoneが返ってきたらログイン画面も終了させる
if main_return is None:
break
window.UnHide() # ログイン画面を再表示する
# チェックボタンが押された時の処理
elif event == "-toggle_password-":
# チェックボタンがONだったらパスワードを表示する
if values["-toggle_password-"]:
window["-password-"].TKEntry.config(show="") # ver 4.35.0以前
# window["-password-"].update(password_char="") # ver 4.35.0以降
# チェックボタンがOFFだったらパスワードを非表示にする
else:
window["-password-"].TKEntry.config(show="*") # ver 4.35.0以前
# window["-password-"].update(password_char="*") # ver 4.35.0以降
# windowを終了させる
window.close()
まとめ
いかがだったでしょうか。
パスワードの表示は簡単でしたが、非表示するのが少し難しかったです。
PySimpleGUIは、Tkinterのラッパー(Tkinterを簡単にしたもの)なので、Tkinterの構造を考えながら実装できる良い機会でした。
DBを用いたデータ認証や、入力欄の自動補完など、自由度が高いようにどんどん付け加えられたら良いなと思います。
こちらの記事が、誰かのお役に立てたら幸いです。
コメントを書く