「PySimpleGUI」は、GUIプログラミングを行うためのライブラリです。Pythonで利用できるGUIライブラリはさまざまですが、PySimpleGUIはとくにシンプルで使いやすいことが魅力です。PySimpleGUIを習得すれば、便利なGUIアプリ・GUIプログラムが作れるようになるでしょう。
しかし、PySimpleGUIは新しく開発されたGUIライブラリなので、得られる情報量が少ないことが難点です。そこで、本記事ではPySimpleGUIの使い方やテクニックについて、サンプルコード付きで詳しく解説します。この記事を読むことで、PySimpleGUIで基本的なGUIアプリが作れるようになるでしょう。
目次
PySimpleGUIとは?

「PySimpleGUI」は、GUIプログラムが手軽に作れるライブラリです。GUIプログラムとは、図形や画像などのグラフィックスを活用し、画面を構成したものを指します。コンソール画面のようなCUIプログラムとは異なり、GUIプログラムを開発するためには専用のライブラリが必要です。
PythonにはさまざまなGUIライブラリがありますが、そのなかでもPySimpleGUIは最も手軽に扱える部類です。PySimpleGUIは、既存のGUIフレームワークである「Tkinter」「PyQt」「WxPython」などを、ベースとして開発されています。これらのGUIライブラリは高機能ではあるものの、覚えるべきクラスやメソッドが多く、ソースコードも長くなりがちです。
一方、PySimpleGUIは既存ライブラリを継承したうえで、よりシンプルなソースコードで機能を実現できるようになっています。実際に、PySimpleGUIで記載したソースコードは、Tkinterの半分以下になることも珍しくありません。そのため、PySimpleGUIは少ない学習期間で高機能なGUIアプリが作れる、非常に魅力的なGUIライブラリです。
PySimpleGUIのメリット

PySimpleGUIのメリットとして、以下の2つがあげられます。
- シンプルにコーディングできる
- 初心者でも手軽に習得しやすい
シンプルにコーディングできる
PySimpleGUIは、とにかく「シンプル」なコーディングができることが、最も大きな魅力です。GUIプログラミングでは、さまざまなパーツを組み合わせて画面を構成するため、多数のオブジェクトの生成や設定を行う必要があります。そのため、全体的にソースコードが長く複雑になりがちです。
しかし、PySimpleGUIは「シンプルなコーディング」を目指して開発されているので、簡潔なソースコードで多くの機能を実装できます。PySimpleGUIを習得すると、GUIアプリを短期間で作れるようになるので、「手早く開発したい」ときに最適なライブラリだといえるでしょう。
初心者でも手軽に習得しやすい
PySimpleGUIは、実装のシンプルさから初心者が習得しやすいことも、大きなメリットです。GUIプログラミングは、専用のライブラリやメソッドを使うため、通常のCUIプログラミングとは異なる点が多いです。
こうした理由から、GUIプログラミングに「ハードルの高さ」を感じてしまう人は少なくありません。一方でPySimpleGUIは、単純なソースコードでGUIの基本機能を実装できるので、初心者でも短期間で習得できます。
さらに、PySimpleGUIには「Cookbook(クックブック)」と呼ばれる公式ドキュメントがあり、基本的なクラスやメソッドの使い方がサンプルコード付きで掲載されています。英語版限定ではありますが、公式による情報提供が充実している点は、学習時の大きなサポートになるでしょう。
PySimpleGUIのデメリット

PySimpleGUIには、以下のようなデメリットもあります。
- 日本語で得られる情報量が少ない
- ライセンス関連の制約に注意が必要
日本語で得られる情報量が少ない
PySimpleGUIの大きなデメリットは、日本語で得られる情報が少ないことです。前述したように、公式のCookbookは英語で記載されており、日本語では提供されていません。そのため、英語が苦手な場合は十分な情報が得られず、学習しにくいでしょう。
しかし、ソースコードは万国共通です。前述したCookbookには、詳細なソースコードが掲載されています。ソースコードの流れを追っていけば、どのような場面でどのメソッドを使うべきか、大まかに理解することは可能です。また、本記事でこれから紹介するサンプルコードも参考にすれば、PySimpleGUIの基本的な部分は網羅できるでしょう。
ライセンス関連の制約に注意が必要
PySimpleGUIは、TkinterのようなGUIライブラリと比べて、「ライセンス」が厳しいことが難点です。PySimpleGUIのライセンスは、「GNU Lesser General Public License v3.0(LGPL 3.0)」というものです。これは、プログラムの配布時は非商用・商用を問わず、すべてのソースコードを公開する必要があることを意味します。
商用目的のアプリをPySimpleGUIで開発した場合は、収益面で不利になる可能性があります。なぜなら、プログラムの公開時にソースコードを開示することで、ほかのプログラマーも同様のGUIアプリが作れるようになるからです。商用目的では、Tkinterのようなライセンス条件が緩いものを選ぶようにするといいでしょう。
PySimpleGUIのインストール方法

PySimpleGUIは、外部ライブラリなのでPython本体には付属していません。そのため、PIPコマンドでPySimpleGUIをインストールする必要があります。まずは、コマンドプロンプトを開いて、以下のコマンドを入力しましょう。
py -m pip install PySimpleGUI

コマンドを入力すると、すぐにPySimpleGUIのインストールが完了し、次のような画面が表示されます。

以上の手順でPySimpleGUIのインストールが完了し、PySimpleGUIを使ってGUIアプリが作れる環境が整います。
【基本編1】PySimpleGUIの基本的な使い方

PySimpleGUIを活用するために欠かせない基本的な使い方について、以下の3つのポイントから解説します。
- ウィンドウを表示する
- ユーザーの入力を受け取る
- イベントループを活用する
ウィンドウを表示する
GUIプログラミングの始まりは、「ウィンドウ」の表示からです。PySimpleGUIでは、あらかじめGUI画面のレイアウトを指定したうえで、「PySimpleGUI.Window()」関数を呼び出すことで、簡単にウィンドウを表示できます。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("1行目の文章")],
[PySimpleGUI.Text("2行目の文章")],
[PySimpleGUI.Text("3行目の文章1"), PySimpleGUI.Text("3行目の文章2")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# ウィンドウの実行処理を行い、ユーザーの入力を待つ
event, values = window.read()
# プログラムを終了する
window.close()
// 実行結果

最初に「レイアウト」を設定している点がポイントです。レイアウトは2次元リストの形式を取ります。1次元リストは「縦に並べる項目」の単位で、1次元リスト内の要素は「横に並べる項目」です。
上記のサンプルプログラムでは、PySimpleGUI.Text()で文字列を表示しています。3つのテキストを縦に並べていますが、3段目の項目は2つのテキストを横に並べています。このように、PySimpleGUIではリストを使って、直感的にレイアウトを決めることが可能です。
また、PySimpleGUI.Window()でウィンドウを生成したあとに、Windowオブジェクトの「read()」関数を呼び出しています。これは、「ユーザーの入力があるまで、ウィンドウを表示し続ける」ための関数です。しかし、今回は入力を受け取るレイアウトを設定していないため、ユーザーが閉じるまでウィンドウは表示され続けます。
ユーザーの入力を受け取る
ユーザーの入力を受け取る場合は、レイアウトに「PySimpleGUI.Input()」を追加します。これだけで、ユーザーが文字を入力できる項目を表示できます。ただし、それだけでは入力値を取得できないので、「PySimpleGUI.Button()」を追加しましょう。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("名前を入力してください")],
[PySimpleGUI.Input()],
[PySimpleGUI.Button("決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# ウィンドウの実行処理を行い、ユーザーの入力を待つ
event, values = window.read()
# ユーザーが入力した名前を反映する
print("こんにちは、" + values[0] + "さん!")
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

コンソール画面

上記のサンプルプログラムでは、ユーザーが名前を入力して「決定」ボタンを押すと、ウィンドウが閉じます。なぜなら、read()関数はユーザーの入力を受けると終了するからです。
このように1回の処理を行う間だけ表示されるウィンドウを「ワンショットウィンドウ」と呼びます。通常のアプリでも、ダイアログなどでワンショットウィンドウが活用されていて、より高度な処理を行う場合は、後述する「イベントループ」を使用します。
イベントループを活用する
先ほどのサンプルプログラムは、ユーザーが反応した段階でメインウィンドウが閉じました。read()の実装が、入力を受けると関数が終了するというものだからです。そのため、ユーザーと双方向のやり取りを続ける場合は、「イベントループ」を活用する必要があります。イベントループは、以下のサンプルプログラムのように無限ループで実装します。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("名前を入力してください")],
[PySimpleGUI.Input(key = "Name")],
[PySimpleGUI.Text(size = (55, 1), key = "Output")],
[PySimpleGUI.Button("決定"), PySimpleGUI.Button("終了")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられるか、「終了」ボタンが押された場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED or event == "終了":
break
# 入力された名前を表示する
window["Output"].update("こんにちは、" + values["Name"] + "さん!")
# プログラムを終了する
window.close()
// 実行結果
入力前

入力後

上記のサンプルプログラムは、ユーザーが名前を入力して「決定」をクリックすると、その内容を反映したメッセージをウィンドウに表示します。重要なポイントは、イベントループを使用している点と、レイアウトのウィジェット(GUI部品)に「key」を追加していることです。
レイアウトで設定している「key」は、いわば「変数名」のようなものです。PySimpleGUI.Input()で設定したkeyは、valuesから値を取り出すときに必要となります。PySimpleGUI.Text()のkeyは、ウィンドウにテキストを反映させるときに使います。それぞれの対応がわかりにくいかもしれませんが、ソースコードを追っていけば慣れるでしょう。
無限ループの内部では、if文でイベントの内容を確認しています。ここにある「終了」は、レイアウトでPySimpleGUI.Button()に指定したボタン名です。ボタンがクリックされると、event変数にボタン名が返ります。あとは、window変数でTextオブジェクトのキーを指定して、update()で新しいテキストを反映させます。
このように無限ループでユーザーと何度もアクションのやり取りを行うウィンドウが「インタラクティブウィンドウ」です。多くのGUIアプリが、ユーザーとの双方向の対話を実現するために、無限ループを活用しています。レイアウトやkeyの使い方が分かれば、次のように複数の入力処理も簡単にできるようになります。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("名前を入力してください"), PySimpleGUI.Input(key = "Name")],
[PySimpleGUI.Text("住所を入力してください"), PySimpleGUI.Input(key = "Address")],
[PySimpleGUI.Text(size = (55, 1), key = "Output")],
[PySimpleGUI.Button("決定"), PySimpleGUI.Button("終了")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられるか、「終了」ボタンが押された場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED or event == "終了":
break
# 入力された名前を表示する
window["Output"].update("こんにちは、" + values["Address"] + "にお住いの" + values["Name"] + "さん!")
# プログラムを終了する
window.close()
// 実行結果
入力前

入力後

【基本編2】PySimpleGUIで使える機能・メソッド

PySimpleGUIで使える代表的な機能・メソッドとして、以下の7種類のものがあげられます。
- popup(ポップアップ)
- Checkbox(チェックボックス)
- Radio(ラジオボタン)
- Listbox(リストボックス)
- Spin(スピン)
- ProgressBar(プログレスバー)
- Image(イメージ)
popup(ポップアップ)
単純なポップアップは、ウィンドウを作成しなくても、「PySimpleGUI.popup()」を呼び出せばわずか1行で表示できます。PySimpleGUI.popup()の使い方は、以下のサンプルコードのとおりです。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# ポップアップを表示する
PySimpleGUI.popup("こんにちは!")
// 実行結果

なお、ポップアップにはさまざまな種類があり、パラメーターの取得や設定も可能です。たとえばPySimpleGUI.popup_get_file()を使うと、以下のようにユーザーが選択したファイルのパスを取得できます。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# ファイルポップアップでファイル名を取得する
filename = PySimpleGUI.popup_get_file("ファイル名を入力してください")
# ポップアップを表示する
PySimpleGUI.popup("選択されたファイルは" + filename + "です")
// 実行結果
選択前

選択後

そのほかにも選択肢の表示やテキストの入力など、さまざまなポップがあります。代表的なポップアップを、以下のサンプルコードで表示してみましょう。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# 「popup_ok」ポップアップを表示する
result = PySimpleGUI.popup_ok("「OK」ボタンを押してください")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_yes_no」ポップアップを表示する
result = PySimpleGUI.popup_yes_no("「Yes」か「No」を選択してください")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_cancel」ポップアップを表示する
result = PySimpleGUI.popup_cancel("「Cancelled」ボタンを押してください")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_ok_cancel」ポップアップを表示する
result = PySimpleGUI.popup_ok_cancel("「OK」か「Cancel」を選択してください")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_error」ポップアップを表示する
result = PySimpleGUI.popup_error("「Error」ボタンを押してください")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_auto_close」ポップアップを表示する
result = PySimpleGUI.popup_auto_close("一定時間で消えるポップアップです")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_quick」ポップアップを表示する
result = PySimpleGUI.popup_quick("一瞬だけポップアップを表示します")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_quick_message」ポップアップを表示する
result = PySimpleGUI.popup_quick_message("一瞬だけポップアップを表示します")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_non_blocking」ポップアップを表示する
result = PySimpleGUI.popup_non_blocking("一瞬だけポップアップを表示します")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_no_buttons」ポップアップを表示する
PySimpleGUI.popup_no_buttons("ボタンがないポップアップを表示します")
# 「popup_notify」ポップアップを表示する
result = PySimpleGUI.popup_notify("通知形式のポップアップを表示します")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_get_date」ポップアップを表示する
result = PySimpleGUI.popup_get_date()
PySimpleGUI.popup(result)
# 「popup_get_folder」ポップアップを表示する
result = PySimpleGUI.popup_get_folder("フォルダーを選択してください")
PySimpleGUI.popup(result + "が選択されました")
# 「popup_get_text」ポップアップを表示する
result = PySimpleGUI.popup_get_text("テキストを入力してください")
PySimpleGUI.popup(result)
// 実行結果
popup_ok

popup_yes_no

popup_cancel

popup_ok_cancel

popup_error

popup_auto_close

popup_quick

popup_quick_message

popup_non_blocking

popup_no_buttons

popup_notify

popup_get_date

popup_get_folder

popup_get_text

PySimpleGUIでは、わずか1行のソースコードを入力するだけで、ユーザーの入力を受け取れる便利なポップアップを表示できます。手間をとらずにウィンドウやレイアウトを作成する必要がないので、積極的に活用しましょう。
なお、popup_notify()とpopup_get_date()は、通常のポップアップとは異なる特殊な形式です。popup_notify()は、ポップアップというよりは通知のような形式で、ユーザーに情報を伝えられます。popup_get_date()は、カレンダー形式のポップアップが表示されるので、ユーザーに生年月日などを選んでもらうときに便利です。
Checkbox(チェックボックス)
「Checkbox(チェックボックス)」は、複数のオプションが選べる選択肢を表示するためのものです。以下のように、PySimpleGUI.Checkbox()を呼び出すことで、レイアウトにチェックボックスを追加できます。
PySimpleGUI.Checkbox(選択肢の項目名)
PySimpleGUI.Checkbox()の引数には、選択肢の項目名を指定しましょう。レイアウトに複数追加すれば、設定した項目名が並び、ユーザーが自由に選択できるようになります。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Checkbox("チェックボックス1")],
[PySimpleGUI.Checkbox("チェックボックス2")],
[PySimpleGUI.Checkbox("チェックボックス3")],
[PySimpleGUI.Ok("決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# ウィンドウの実行処理を行い、ユーザーの入力を待つ
event, values = window.read()
# ユーザーの選択を表示する
print(values)
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

コンソール画面

無限ループを使用する「インタラクティブウィンドウ」を作成する場合は、PySimpleGUI.Checkbox()に「key変数」を追加し、イベント処理時に「values[キー]」とすることでユーザーが入力したデータを取得できます。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Checkbox("チェックボックス1", key = "Check1", default = True)],
[PySimpleGUI.Checkbox("チェックボックス2", key = "Check2")],
[PySimpleGUI.Checkbox("チェックボックス3", key = "Check3")],
[PySimpleGUI.Ok("決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられるか、「終了」ボタンが押された場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# 「決定」ボタンが押された場合は、要素の取得処理を行う
if event == "決定":
# メッセージを格納するための変数
message = ""
# 各チェックボックスのチェック状態を調べる
# 選択されている場合はメッセージに追加する
if values["Check1"] == True:
message += "「チェックボックス1」\n"
if values["Check2"] == True:
message += "「チェックボックス2」\n"
if values["Check3"] == True:
message += "「チェックボックス3」\n"
# 合成したメッセージを表示する
PySimpleGUI.popup(message + "が選択されました!")
break
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

ポップアップ

ウィジェット生成時に「key変数」を設定しておくことで、read()の戻り値「values変数」で値を取得できます。これは、ほかのウィジェットでも同じことなので覚えておきましょう。
Radio(ラジオボタン)
「Radio(ラジオボタン)」は、複数の選択肢からひとつだけ選べるウィジェットです。PySimpleGUI.Radio()を以下の構文で呼び出すと、ラジオボタンを表示できます。
PySimpleGUI.Radio(チェックボックスの項目名, group_id = グループID)
重要なポイントは、「group_id引数」を設定することです。group_idを設定することで、ラジオボタンのグループを設定できます。ユーザーが選択できるのは、同じgroup_idを設定した項目のうち1つだけです。誤ってすべて別々のgroup_idを設定すると、複数の選択肢を選べてしまうので注意が必要です。詳細を以下のサンプルコードで確認しましょう。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("グループ1")],
[PySimpleGUI.Radio("チェックボックス1", group_id = "radio_1")],
[PySimpleGUI.Radio("チェックボックス2", group_id = "radio_1")],
[PySimpleGUI.Radio("チェックボックス3", group_id = "radio_1")],
[PySimpleGUI.Text("グループ2")],
[PySimpleGUI.Radio("チェックボックス4", group_id = "radio_2")],
[PySimpleGUI.Radio("チェックボックス5", group_id = "radio_2")],
[PySimpleGUI.Radio("チェックボックス6", group_id = "radio_2")],
[PySimpleGUI.Ok("決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# ウィンドウの実行処理を行い、ユーザーの入力を待つ
event, values = window.read()
# ユーザーの選択を表示する
print(values)
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

コンソール画面

無限ループでイベントを処理する場合は、「key変数」で変数名を付けておき、イベント処理時にvalues変数から取得します。なお、default引数をTrueにすれば、初期状態でその項目が選択されている状態になります。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("グループ1")],
[PySimpleGUI.Radio("チェックボックス1", group_id = "radio_1", key = "Radio1", default = True)],
[PySimpleGUI.Radio("チェックボックス2", group_id = "radio_1", key = "Radio2")],
[PySimpleGUI.Radio("チェックボックス3", group_id = "radio_1", key = "Radio3")],
[PySimpleGUI.Text("グループ2")],
[PySimpleGUI.Radio("チェックボックス4", group_id = "radio_2", key = "Radio4")],
[PySimpleGUI.Radio("チェックボックス5", group_id = "radio_2", key = "Radio5")],
[PySimpleGUI.Radio("チェックボックス6", group_id = "radio_2", key = "Radio6", default = True)],
[PySimpleGUI.Ok("決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられるか、「終了」ボタンが押された場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# 「決定」ボタンが押された場合は、要素の取得処理を行う
if event == "決定":
# メッセージを格納するための変数
message = ""
# 各チェックボックスのチェック状態を調る
# 選択されている場合はメッセージに追加する
for i in range(6):
if values["Radio" + str(i + 1)] == True:
message += "「チェックボックス」" + str(i + 1) + "\n"
# 合成したメッセージを表示する
PySimpleGUI.popup(message + "が選択されました!")
break
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

ポップアップ

上記のサンプルプログラムでは、forループでユーザーの入力値の取得とメッセージの作成を行っています。それ以外はチェックボックスの場合と同じです。
Listbox(リストボックス)
「Listbox(リストボックス)」は、リスト形式でユーザーに選択肢を表示するウィジェットです。あらかじめリスト変数で選択肢を設定したうえで、以下の構文でPySimpleGUI.Listbox()を呼び出すと、リストボックスを表示できます。
PySimpleGUI.Listbox(選択肢を指定したリスト, size = (None, len(選択肢を指定したリスト)))
重要なポイントは、第1引数にリストを引き渡すことです。また、size引数を設定しておかないと、リストが正しく表示されないことがあります。Listboxの使い方について、以下のサンプルコードで確認しましょう。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# リストボックスのアイテムを指定する
items = ["アイテムA", "アイテムB", "アイテムC"]
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("どれを選びますか?")],
[PySimpleGUI.Listbox(items, size = (None, len(items)))],
[PySimpleGUI.Ok("決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# ウィンドウの実行処理を行い、ユーザーの入力を待つ
event, values = window.read()
# ユーザーの選択を表示する
print(values)
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

コンソール画面

無限ループ内でイベントを処理する場合は、ほかのウィジェット同様に「key引数」を指定します。ただし、ユーザーが選んだ選択肢はvaluesではなく、ウィンドウオブジェクトの「window」から取得する必要があります。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# リストボックスのアイテムを指定する
items = ["アイテムA", "アイテムB", "アイテムC"]
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("どれを選びますか?")],
[PySimpleGUI.Listbox(items, size = (None, len(items)), key = "list", select_mode = PySimpleGUI.LISTBOX_SELECT_MODE_MULTIPLE)],
[PySimpleGUI.Ok("決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられるか、「終了」ボタンが押された場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# 「決定」ボタンが押された場合は、要素の取得処理を行う
if event == "決定":
# メッセージを格納するための変数
message = ""
# 選択された項目のインデックスを取得する
indexes = window["list"].get_indexes()
# インデックスの一覧情報から、選択された要素を表示する
for i in range(len(indexes)):
message += str(items[indexes[i]]) + "\n"
# 合成したメッセージを表示する
PySimpleGUI.popup(message + "が選択されました!")
break
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

コンソール画面

上記のように、「window[リストのキー].get_indexes()」とすることで、ユーザーが選択したリストのインデックスを取得できます。最初に作成したリスト変数に、そのインデックスでアクセスすれば、どの要素が選択されたか把握できます。
なお、上記のサンプルプログラムでは「select_mode = PySimpleGUI.LISTBOX_SELECT_MODE_MULTIPLE」を追加し、ユーザーが複数のオプションを選べるようにしていることがポイントです。get_indexes()を使えば、複数の選択結果もすべて取得できるので便利です。
Spin(スピン)
エディットボックスの右側の矢印で値を選択できる「Spin(スピン)」は、「PySimpleGUI.Spin()」で表示できます。まずは、リスト形式で要素を指定したうえで、以下の構文で引数を指定しましょう。
PySimpleGUI.Spin(選択肢を指定したリスト)
ほかのウィジェットと同じように、わずか1行だけのコードで必要な機能を実装できます。PySimpleGUI.Spin()の使い方を、以下のサンプルコードで確認しましょう。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# スピンのアイテムを指定する
zodiac = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未" ,"申", "酉", "戌" , "亥"]
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("どれを選びますか?")],
[PySimpleGUI.Spin(zodiac)],
[PySimpleGUI.Ok("決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# ウィンドウの実行処理を行い、ユーザーの入力を待つ
event, values = window.read()
# ユーザーの選択を表示する
print(values)
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

コンソール画面

インタラクティブウィンドウで実装する場合は、以下のサンプルコードのように「key引数」で変数名を設定し、イベント処理時にvalues変数からデータを取得します。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# スピンのアイテムを指定する
zodiac = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未" ,"申", "酉", "戌" , "亥"]
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("どれを選びますか?")],
[PySimpleGUI.Spin(zodiac, key = "spin")],
[PySimpleGUI.Ok("決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられるか、「終了」ボタンが押された場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# 「決定」ボタンが押された場合は、要素の取得処理を行う
if event == "決定":
# スピンから選択された要素を表示する
PySimpleGUI.popup(values["spin"] + "が選択されました!")
break
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

ポップアップ

ProgressBar(プログレスバー)
「ProgressBar(プログレスバー)」は、処理の進行状況をバーで表示するためのものです。以下の構文でPySimpleGUI.ProgressBar()を呼び出して引数を指定すると、プログレスバーを簡単に表示できます。
PySimpleGUI.ProgressBar(分割数, orientation = "方向", size = (横サイズ, 縦サイズ), key = キー)
分割数は、プログレスバーの進行段階を示します。この値を100にすると、100段階で値を変化させることが可能です。「orientation引数」はプログレスバーの方向を示し、横方向は「h」・縦方向は「v」となります。「size引数」はプログレスバーのサイズです。
なお、プログレスバーは連続して値の変更処理を行うため、基本的には無限ループを回してイベントを処理します。そのため、「key引数」によるキー設定が必要です。PySimpleGUI.ProgressBar()の使い方について、以下のサンプルコードで確認しましょう。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("処理中…")],
[PySimpleGUI.ProgressBar(100, orientation = "h", size = (20, 20), key = "bar")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# ループ処理でプログレスバーを進行させる
for i in range(100):
# read()関数の「timeout引数」を設定すると、指定時間だけ処理を待機できる
event, values = window.read(timeout = 20)
# イベントの処理を行う
# ウィンドウが閉じられるか、「終了」ボタンが押された場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# プログレスバーを更新する
window["bar"].update(i + 1)
# プログラムを終了する
window.close()
// 実行結果

重要なポイントは、無限ループの内部でプログレスバーの値を変更していることです。ウィンドウオブジェクトでキーを指定し、「update()」を呼び出すことで、プログレスバーの進行状態を変更できます。なお、forループの回数は、事前に設定した分割数と同じにしましょう。
また「orientation引数」の値を「”v”」にすると、以下のようにプログレスバーが縦向きになります。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("処理中…")],
[PySimpleGUI.ProgressBar(100, orientation = "v", size = (20, 20), key = "bar")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# ループ処理でプログレスバーを進行させる
for i in range(100):
# read()関数の「timeout引数」を設定すると、指定時間だけ処理を待機できる
event, values = window.read(timeout = 20)
# イベントの処理を行う
# ウィンドウが閉じられるか、「終了」ボタンが押された場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# プログレスバーを更新する
window["bar"].update(i + 1)
# プログラムを終了する
window.close()
// 実行結果

このように引数を少し変更するだけで、さまざまなバリエーションのプログレスバーを表示できます。数秒以上かかるような処理を行うときにプログレスバーを表示すると、ユーザーフレンドリーなGUIアプリになります。
Image(イメージ)
PySimpleGUIには、画像を表示する機能も備わっています。PySimpleGUI.Image()を以下の構文で呼び出すだけで、ウィンドウに任意の画像を表示できます。
PySimpleGUI.Image(ファイルパス, key = キー)
なお、ウィンドウのサイズは画像に合わせて自動的に決まります。以下の画像を「Sample.png」という名称で、メインモジュールがあるディレクトリに保存したうえで、サンプルコードを実行しましょう。

// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Image("Sample.png", key = "image")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられた場合は処理を終了する
if event == PySimpleGUI.WIN_CLOSED:
break
# プログラムを終了する
window.close()
// 実行結果

一般的なGUIライブラリでは、1枚の画像をウィンドウに表示するだけでも、相当量のソースコードが必要になります。PySimpleGUIはわずか1行のコードで、画像の読み込みからレイアウト設定まで可能です。この点からも、PySimpleGUIは便利なGUIライブラリだといえるでしょう。
【応用編1】画像の加工や編集を行う方法

PySimpleGUIには、前述したような画像の表示機能はあるものの、画像を加工・編集する機能はありません。高度な画像加工を行うためには、「OpenCV」というライブラリと組み合わせるのがおすすめです。
OpenCVは、複雑な画像処理を簡潔なプログラムで行うための、便利なライブラリです。ただし、Pythonに標準搭載されているライブラリではないので、以下のようにPIPコマンドでインストールする必要があります。まずは、コマンドプロンプトを開きましょう。
py -m pip install opencv-python

OpenCVは大容量のライブラリなので、インストール完了までしばらく時間がかかります。コンソール画面がフリーズしたような状態になることもありますが、インストールは続いているため、以下のような画面が表示されるまでお待ちください。

以上の手順で、PythonでOpenCVが使えるようになります。ここでは、OpenCVとPySimpleGUIを組み合わせた、以下の2つのテクニックをご紹介します。
- 画像をリサイズする
- 色調を変換した画像を保存する
画像をリサイズする
画像をリサイズしたいときは、以下の構文で「cv2.resize()関数」を使用します。
変換後の画像データ = cv2.resize(変換前の画像データ, (0, 0), fx = X軸方向のスケール, fy = Y軸方向のスケール, interpolation = 補間方法)
OpenCVでは、画像の読み込みを「cv2.imread(ファイルパス)」という構文で行います。その戻り値として返ってきた画像データを、cv2.resize()の第1引数に引き渡すことがポイントです。第2引数は「(0, 0)」のタプルを引き渡せばOKです。「fx」と「fy」には、縦横のスケール値をそれぞれ引き渡します。デフォルトのサイズは1.0となっており、これより小さくすると縮小、大きくすると拡大になります。
「interpolation引数」には、リサイズ時の「補間方法」を指定し、これによって変換後の画像の品質が変わることがポイントです。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# 「cv2」ライブラリをimportする
import cv2
# ファイルポップアップでファイル名を取得する
filename = PySimpleGUI.popup_get_file("リサイズする画像ファイルを選択してください")
# 画像ファイルを読み込む
# CV2はASCII文字にしか対応していないため
# ファイルパスに日本語を含めるとエラーが出る
image = cv2.imread(filename)
# 画像をウィンドウに表示する
# ウィンドウ名もアスキー文字のみ対応
cv2.imshow("OpenCV Sample", image)
# 画像のサイズを取得する
height, width = image.shape[:2]
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text(f"横方向の倍率"), PySimpleGUI.Input(key = "Width")],
[PySimpleGUI.Text(f"縦方向の倍率"), PySimpleGUI.Input(key = "Height")],
[PySimpleGUI.Button("画像をリサイズする")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# すべてのウィンドウを閉じる
cv2.destroyAllWindows()
# イベントの処理を行う
# ウィンドウが閉じられた場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# 「画像をリサイズする」ボタンが押された場合は、画像のリサイズ処理を行う
if event == "画像をリサイズする":
# 画像をリサイズする
image = cv2.resize(image, (0, 0), fx = float(values["Width"]), fy = float(values["Height"]), interpolation = cv2.INTER_CUBIC)
break
# プログラムを終了する
window.close()
# 画像をウィンドウに表示する
# ウィンドウ名もアスキー文字のみ対応
cv2.imshow("OpenCV Sample", image)
# ユーザーのキー入力を待つ
cv2.waitKey(0)
# すべてのウィンドウを閉じる
cv2.destroyAllWindows()
// 実行結果
初期画面

画像オープン時

リサイズ後

上記のサンプルプログラムでは、PySimpleGUI.popup_get_file()でファイルダイアログを開き、OpenCVの機能で画像を読み込んでいます。そのうえで、新しいウィンドウを表示してユーザーにスケールの入力を促し、「画像をリサイズする」ボタンが押されたときにcv2.resize()でリサイズ処理を行います。
なお、cv2.resize()の「interpolation引数」には以下のような値を設定可能です。値によって、リサイズの品質が大きく変わります。
| interpolationの値 | 補間方法 |
|---|---|
| cv2.INTER_NEAREST | 最近傍補間 |
| cv2.INTER_LINEAR | バイリニア補間 |
| cv2.INTER_CUBIC | バイキュービック補間 |
| cv2.INTER_AREA | 平均画素法 |
| cv2.INTER_LANCZOS4 | Lanczos(ランチョス)法 |
画像を拡大する場合は「cv2.INTER_CUBIC」が、画像を縮小する場合は「cv2.INTER_AREA」が最も高品質になる傾向があります。interpolation引数によってリサイズのクオリティが変わるため、用途に合うものを選びましょう。
色調を変換した画像を保存する
OpenCVで画像を保存するときは、以下の構文で「cv2.imwrite()」関数を使いましょう。
cv2.imwrite("出力先ファイル名", 画像データ)
また、OpenCVにはさまざまな「色調変換」のための機能が搭載されています。画像の色調変換は、「cv2.cvtColor()」関数で行います。
変換後の画像データ = cv2.cvtColor(変換前の画像データ, 変換方法)
第2引数に「cv2.COLOR_BGR2GRAY」を引き渡せば、画像がグレースケールになります。グレースケール化した画像は、「cv2.threshold()関数」で白と黒の2色だけの「2値化」を行うことも可能です。
結果, 2値化した画像データ = cv2.threshold(グレースケール画像, 白黒の閾値, 255, cv2.THRESH_BINARY)
第3引数と第4引数は、基本的には「255」と「cv2.THRESH_BINARY」に固定しておけばOKです。これらの点を踏まえて、画像をさまざまな形式に変換してみましょう。使用する画像はこれまでのサンプルプログラムと同じです。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# 「cv2」ライブラリをimportする
import cv2
# ファイルポップアップでファイル名を取得する
filename = PySimpleGUI.popup_get_file("変換する画像ファイルを選択してください")
# 画像ファイルを読み込む
# CV2はASCII文字にしか対応していないため
# ファイルパスに日本語を含めるとエラーが出る
image = cv2.imread(filename)
# 画像のサイズを取得する
height, width = image.shape[:2]
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text(f"横方向の倍率"), PySimpleGUI.Input(key = "Width")],
[PySimpleGUI.Text(f"縦方向の倍率"), PySimpleGUI.Input(key = "Height")],
[PySimpleGUI.Button("画像をリサイズする")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられた場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# 「画像をリサイズする」ボタンが押された場合は、画像のリサイズ処理を行う
if event == "画像をリサイズする":
# 画像をリサイズする
image = cv2.resize(image, (0, 0), fx = float(values["Width"]), fy = float(values["Height"]), interpolation = cv2.INTER_CUBIC)
break
# プログラムを終了する
window.close()
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Button("グレースケール化")], [PySimpleGUI.Button("2値化")], [PySimpleGUI.Button("HSV化")], [PySimpleGUI.Button("YCrCb化")], [PySimpleGUI.Button("XYZ化")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられた場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# 「グレースケール化」ボタンが押された場合は、画像をグレースケールに変換して保存する
if event == "グレースケール化":
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imwrite("gray_image.png", gray_image)
break
# 「2値化」ボタンが押された場合は、画像を2値化して保存する
if event == "2値化":
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
result, threshold_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)
cv2.imwrite("threshold_image.png", threshold_image)
break
# 「HSV化」ボタンが押された場合は、画像をHSV形式に変換して保存する
if event == "HSV化":
HSV_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
cv2.imwrite("HSV_image.png", HSV_image)
break
# 「YCrCb化」ボタンが押された場合は、画像をYCrCb形式に変換して保存する
if event == "YCrCb化":
YCrCb_image = cv2.cvtColor(image, cv2.COLOR_BGR2YCrCb)
cv2.imwrite("YCrCb_image.png", YCrCb_image)
break
# 「XYZ化」ボタンが押された場合は、画像をXYZ形式に変換して保存する
if event == "XYZ化":
XYZ_image = cv2.cvtColor(image, cv2.COLOR_BGR2XYZ)
cv2.imwrite("XYZ_image.png", XYZ_image)
break
// 実行結果
初期画面

リサイズ画面

変換画面

gray_image.png

threshold_image.png

HSV_image.png

YCrCb_image.png

XYZ_image.png

上記のサンプルプログラムでは、リサイズ設定のウィンドウを開いたあとに、5つの変換方法のボタンを表示しています。「グレースケール化」「2値化」「HSV化」「YCrCb化」「XYZ化」のいずれかをクリックすると、色調変換が行われます。
【応用編2】PySimpleGUIで知っておくと便利なこと

PySimpleGUIをより便利に使うために効果的な、以下の5つのテクニックも紹介します。
- 「画面遷移」を行う
- ウィンドウの透明度を変更する
- テキストの枠線の種類を変更する
- PySimpleGUIの「テーマ」を変更する
- 複雑なレイアウトを設定する
「画面遷移」を行う
GUIアプリで重要になるのが「画面遷移」です。画面遷移とは、現在のウィンドウから別のウィンドウに画面を切り替えて、異なる情報をユーザーに示すことを指します。PySimpleGUIでは、以下のように必要なタイミングでウィンドウの生成と破棄を行うことで、スムーズな画面遷移を行うことが可能です。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# MainWindowクラス|メインウィンドウの処理を行う
class MainWindow:
# コンストラクタ
def __init__(self):
# レイアウトを指定する
layout = [[PySimpleGUI.Text("メインウィンドウ")],
[PySimpleGUI.Button("サブウィンドウを開く")],
[PySimpleGUI.Button("プログラムを終了する")]]
# ウィンドウを表示する
self.window = PySimpleGUI.Window("メインウィンドウ", layout)
# process()関数|ウィンドウのループ処理を行う
def process(self):
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = self.window.read()
# イベントの処理を行う
# ウィンドウが閉じられた、もしくは「プログラムを終了する」が押された場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED or event == "プログラムを終了する":
# プログラムを終了する
self.window.close()
# ウィンドウが閉じられた場合はFalseを返す
return False
# 「サブウィンドウを開く」ボタンが押された場合は、サブウィンドウを開く
if event == "サブウィンドウを開く":
# プログラムを終了する
self.window.close()
# ウィンドウが閉じられた場合はTrueを返す
return True
# SubWindowクラス|サブウィンドウの処理を行う
class SubWindow:
# コンストラクタ
def __init__(self):
# レイアウトを指定する
layout = [[PySimpleGUI.Text("サブウィンドウ")],
[PySimpleGUI.Button("ポップアップを表示する")],
[PySimpleGUI.Button("サブウィンドウを閉じる")]]
# ウィンドウを表示する
self.window = PySimpleGUI.Window("サブウィンドウ", layout)
# process()関数|ウィンドウのループ処理を行う
def process(self):
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = self.window.read()
# イベントの処理を行う
# ウィンドウが閉じられた、もしくは「サブウィンドウを閉じる」が押された場合は、メインウィンドウに戻る
if event == PySimpleGUI.WINDOW_CLOSED or event == "サブウィンドウを閉じる":
# プログラムを終了する
self.window.close()
break
# 「ポップアップを表示する」ボタンが押された場合は、ポップアップを表示する
if event == "ポップアップを表示する":
# ポップアップを表示する
PySimpleGUI.popup("ポップアップ")
# ウィンドウを閉じる
self.window.close()
# __main__()関数|プログラムのエントリーポイント
if __name__ == "__main__":
# 無限ループでウィンドウの処理を行う
while True:
# メインウィンドウを表示する
main_window = MainWindow()
# メインウィンドウの処理を行う
result = main_window.process()
# 戻り値が「True」の場合は、サブウィンドウを表示する
if result == True:
# サブウィンドウを表示する
sub_window = SubWindow()
# サブウィンドウの処理を行う
sub_window.process()
# 戻り値が「False」の場合は、プログラムを終了する
else:
break
// 実行結果
メインウィンドウ

サブウィンドウ

ポップアップ

上記のサンプルプログラムでは、ウィンドウのクラスを個別に生成して、イベントループ内で別ウィンドウの生成などのタイミングを調整しています。Main関数内で無限ループを回すことで、画面遷移を何度でも繰り返せます。このテクニックは、さまざまな場面で活用できるので、ぜひ活用してみてください。
ウィンドウの透明度を変更する
PySimpleGUIでは、PySimpleGUI.Window()に「alpha_channel引数」を設定することで、ウィンドウの「透明度」を変更できます。「1.0」がデフォルトの不透明状態で、これが「0.0」に近付くほどウィンドウが透明になります。以下のサンプルコードで、ウィンドウの透明度を変更してみましょう。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# PySimpleGUIのテーマを変更する
PySimpleGUI.theme("Dark Blue")
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("透明度のテスト")]]
# レイアウトを反映させたウィンドウを表示する
# アルファチャンネルの値を「0.5」にしているため、半透明のウィンドウになる
window = PySimpleGUI.Window("サンプル", layout, alpha_channel = 0.5)
# ユーザーの入力を取得する
event, values = window.read()
# プログラムを終了する
window.close()
// 実行結果

GUIデザインの都合上、ウィンドウを半透明にしたほうが良いこともあります。ただし、alpha_channel引数の値を下げすぎると、テキストやボタンが見づらくなってしまうので注意が必要です。
テキストの枠線の種類を変更する
PySimpleGUIで最も使用頻度が高いウィジェットのひとつが「テキスト」です。実は、テキストの生成時に「relief引数」を設定すると、テキストの枠線をさまざまな形式に変更できます。relief引数には、以下のような値を設定できます。
- PySimpleGUI.RELIEF_SOLID
- PySimpleGUI.RELIEF_RAISED
- PySimpleGUI.RELIEF_SUNKEN
- PySimpleGUI.RELIEF_FLAT
- PySimpleGUI.RELIEF_RIDGE
- PySimpleGUI.RELIEF_GROOVE
選択する枠線によって、テキストのデザインや見やすさが大きく変わります。それぞれどのようなデザインになるか、以下のサンプルコードで確認してみましょう。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# PySimpleGUIのテーマを変更する
PySimpleGUI.theme("Dark Blue")
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("テキスト", relief = PySimpleGUI.RELIEF_SOLID, border_width = 5)],
[PySimpleGUI.Text("テキスト", relief = PySimpleGUI.RELIEF_RAISED, border_width = 5)],
[PySimpleGUI.Text("テキスト", relief = PySimpleGUI.RELIEF_SUNKEN, border_width = 5)],
[PySimpleGUI.Text("テキスト", relief = PySimpleGUI.RELIEF_FLAT, border_width = 5)],
[PySimpleGUI.Text("テキスト", relief = PySimpleGUI.RELIEF_RIDGE, border_width = 5)],
[PySimpleGUI.Text("テキスト", relief = PySimpleGUI.RELIEF_GROOVE, border_width = 5)]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# ユーザーの入力を取得する
event, values = window.read()
# プログラムを終了する
window.close()
// 実行結果

デフォルト設定は「PySimpleGUI.RELIEF_SOLID」で、通常の枠線となります。「PySimpleGUI.RELIEF_RAISED」は盛り上がった形、「PySimpleGUI.RELIEF_SUNKEN」は沈み込んだ形です。一方、「PySimpleGUI.RELIEF_FLAT」は枠線なしのフラット表示、「PySimpleGUI.RELIEF_RIDGE」や「PySimpleGUI.RELIEF_GROOVE」は太い枠線となります。
PySimpleGUIの「テーマ」を変更する
PySimpleGUIには、さまざまな「テーマ」が用意されており、切り替えることでウィンドウの見た目を変更できます。以下のように、「PySimpleGUI.theme_previewer()」関数を呼び出すと、大きな画面に膨大な数のテーマが表示されます。
// サンプルプログラム
# coding: UTF-8 # 「PySimpleGUI」ライブラリをimportする import PySimpleGUI # PySimpleGUIの「テーマ」一覧画面を表示する PySimpleGUI.theme_previewer()
// 実行結果

実際のテーマ変更は、「PySimpleGUI.theme()」関数を呼び出すことで行います。そのうえで適当なポップアップを表示すると、次のようにテーマの変更を確認できます。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# change_theme()関数|テーマを変更する
def change_theme(theme):
PySimpleGUI.theme(theme)
PySimpleGUI.popup("テーマ変更")
# 3種類のテーマを試す
change_theme("DarkBlue")
change_theme("GrayGrayGray")
change_theme("HotDogStand")
// 実行結果
DarkBlue

GrayGrayGray

HotDogStand

また、存在しないテーマを選択すると、次のようなエラー画面が表示され、どのテーマが選べるかを確認できます。

複雑なレイアウトを設定する
PySimpleGUIでは、複雑な「入れ子」のレイアウトで、GUI画面を構成することもできます。たとえば、ユーザーに氏名・住所・電話番号を入力してもらう場合は、通常のレイアウトでは以下のようになります。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# PySimpleGUIのテーマを変更する
PySimpleGUI.theme("Dark Blue")
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("Python GUI")],
[PySimpleGUI.Text("氏名", size = (15, 1)), PySimpleGUI.InputText(key = "Name")],
[PySimpleGUI.Text("住所", size = (15, 1)), PySimpleGUI.InputText(key = "Address")],
[PySimpleGUI.Text("電話番号", size = (15, 1)), PySimpleGUI.InputText(key = "Phone")],
[PySimpleGUI.Submit(button_text = "決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられた場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# 「決定」ボタンが押された場合は、入力内容を反映させたポップアップを表示する
if event == "決定":
# メッセージを格納するための変数
message = ""
# メッセージを生成する
message += "氏名:" + values["Name"] + "\n"
message += "住所:" + values["Address"] + "\n"
message += "電話番号:" + values["Phone"]
# ポップアップを表示する
PySimpleGUI.popup(message)
break
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

ポップアップ

Frameオブジェクトを使うと、ウィジェットのまとまりを作れます。Frameオブジェクトは、以下の構文で生成できます。
PySimpleGUI.Frame(フレーム名, フレーム構造, relief = 枠線の種類, tooltip = ヒント表示)
第1引数には、フレーム上部に表示するテキストを指定します。たとえば住所氏名などを入力するフレームを作るのであれば、「住所」でいいでしょう。第2引数には、フレーム内部のウィジェットを定義します。これは、今までの「レイアウト」とまったく同じです。
これ以降の引数は、必要がなければ指定しなくても構いません。「relief引数」は、先ほど解説したテキストと同じく枠線の種類を選べます。「tooltip引数」は、マウスカーソルを合わせたときに表示されるヒントです。あとはフレームをレイアウトのリストに追加するだけで、入れ子のレイアウトを実現できます。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム
# coding: UTF-8
# 「PySimpleGUI」ライブラリをimportする
import PySimpleGUI
# PySimpleGUIのテーマを変更する
PySimpleGUI.theme("Dark Blue")
# 入れ子にする要素を設定する
inner = [[PySimpleGUI.Text("郵便番号", size = (15, 1))],
[PySimpleGUI.InputText(key = "Post")],
[PySimpleGUI.Text("都道府県", size = (15, 1))],
[PySimpleGUI.InputText(key = "Prefecture")],
[PySimpleGUI.Text("市区町村", size = (15, 1))],
[PySimpleGUI.InputText(key = "Town")],
[PySimpleGUI.Text("番地", size = (15, 1))],
[PySimpleGUI.InputText(key = "Number")]]
# 入れ子にするためのフレームを構成する
frame = PySimpleGUI.Frame("住所", inner, relief = PySimpleGUI.RELIEF_SUNKEN, tooltip = "住所を入力してください")
# GUI画面のレイアウトを構成する
layout = [[PySimpleGUI.Text("Python GUI")],
[PySimpleGUI.Text("氏名", size = (15, 1)), PySimpleGUI.InputText(key = "Name")],
[PySimpleGUI.Text("住所", size = (15, 1)), frame],
[PySimpleGUI.Text("電話番号", size = (15, 1)), PySimpleGUI.InputText(key = "Phone")],
[PySimpleGUI.Submit(button_text = "決定")]]
# レイアウトを反映させたウィンドウを表示する
window = PySimpleGUI.Window("サンプル", layout)
# イベントループを使用し、インタラクティブウィンドウを表示する
while True:
# ユーザーの入力を取得する
event, values = window.read()
# イベントの処理を行う
# ウィンドウが閉じられた場合は処理を終了する
if event == PySimpleGUI.WINDOW_CLOSED:
break
# 「決定」ボタンが押された場合は、入力内容を反映させたポップアップを表示する
if event == "決定":
# メッセージを格納するための変数
message = ""
# メッセージを生成する
message += "氏名:" + values["Name"] + "\n"
message += "住所:" + values["Post"] + " " + values["Prefecture"] + " " + values["Town"] + " " + values["Number"] + "\n"
message += "電話番号:" + values["Phone"]
# ポップアップを表示する
PySimpleGUI.popup(message)
break
# プログラムを終了する
window.close()
// 実行結果
メインウィンドウ

ポップアップ

上記のサンプルプログラムは、「住所」の入力部分を「郵便番号」「都道府県」「市区町村」「番地」の4つで分割しています。フレームのrelief引数を「PySimpleGUI.RELIEF_SUNKEN」にしているため、他の部分との区別がつきやすいこともポイントです。なお、住所のフレーム部分にマウスカーソルを合わせると、「住所を入力してください」というヒントが表示されます。
このように、PySimpleGUIはGUI画面のデザイン機能が豊富なので、これまで紹介した方法を組み合わせてさまざまなパターンを試してみましょう。
PySimpleGUIを活用してGUIアプリを手軽に作ろう

PySimpleGUIを使うことで、シンプルなソースコードで高度なGUIアプリを開発できます。既存のGUIライブラリで何行も書かないといけない処理が、PySimpleGUIではわずか数行で実装できます。そのため、ほかのGUIライブラリの習得が難しい人でも、PySimpleGUIなら気軽に使えるかもしれません。この機会にぜひ、PythonのPySimpleGUIを活用してみてください。