Python GUIライブラリ各種¶
PythonでGUIは可能か¶
実はPythonには標準ライブラリで、Tkinterが提供されています。 Tcl/TkのPythonバインディングです。少し癖がありますが、Tcl/Tkに馴染みがあれば理解が容易でしょう。
標準以外にも多数のGUIライブラリが存在します。
いろいろなPython GUIライブラリ¶
ここでは、いろいろなPythonのGUIライブラリのざっくり概要と、ボタンをクリックするとあいさつ文を表示するごく簡単な画面を持つプログラムを書いて比較します。
Tkinter¶
ごく基本的なウィジェットと、3種類のレイアウト(ジオメトリマネージャ)があります。
ウィジェットは、Label、Entry(1行テキスト入力)、Message(複数行テキスト入力)、Button、RadioButton、CheckButton、ListBox、Scrollbar、Scale、MenuButton、Text、Spinbox、Frame、LabelFrame、PanedWindow、Bitmap、Canvasなどです。
レイアウトは次の3種があります。
- Placer
絶対座標指定でウィジェットを配置 - Packer
ウィンドウにウィジェットを詰め込む - Gridder
ウィジェットを格子状に配置
GUI処理のイベントループは、Tkクラスのmainloopメソッドを実行します。
Hello, world¶
from tkinter import Tk, Frame, Button, Label
class Application(Frame):
def __init__(self, master=None):
super().__init__(master)
self.label = Label(master)
self.label.pack()
button = Button(
master, text='ご挨拶',
command=lambda: self.label.configure(text='Hello, world.')
)
button.pack()
if __name__ == "__main__":
root = Tk()
app = Application(master=root)
app.mainloop()
- Tk()でトップレベルウィンドウを生成
- Frame派生のApplicationクラスを定義
- Labelを生成、テキストは空
- Buttonを生成、ボタンに表示するテキスト、ボタンが押された際の処理を定義
- mainloop実行
Kivi¶
ライセンス | MIT |
画面の記述をPythonコードだけでなく、Kv言語で記述することができます。
レイアウトは、AnchorLayout、BoxLayout、FloatLayout、RelativeLayout、GridLayout、PageLayout、ScatterLayout、StackLayoutがあります。
標準では日本語が文字化けします。
hello world (Pythonコードのみで記述)¶
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
class HelloScreen(BoxLayout):
def __init__(self):
super().__init__()
self.orientation = 'vertical'
self.label = Label()
self.add_widget(self.label)
self.button = Button(text='Greeting')
self.button.bind(on_press=self.handle_greeting)
self.add_widget(self.button)
def handle_greeting(self, event):
self.label.text = 'Hello, world.'
class HelloApp(App): # GUIアプリケーションクラスを定義
def build(self):
return HelloScreen()
if __name__ == '__main__':
HelloApp().run()
- Appを派生しGUIアプリケーションクラスHelloAppを定義、buildメソッドはウィンドウ内のトップウィジェットを生成し返却する
- トップレベルウィジェットはBoxLayoutを派生したHelloScreenクラスを定義
- 配置を垂直方向(vertical)と指定
- LabelとButtonを生成
- Buttonがクリックされたときは、メソッドhandle_greetingを呼ぶよう紐づけ
- イベントループは、App派生クラスのrunメソッドを呼ぶ
hello world (PythonとKv言語で記述)¶
- hello_app.py
from kivy.app import App from kivy.uix.widget import Widget from kivy.properties import StringProperty class HelloScreen(Widget): text = StringProperty('') def on_button_click(self): self.text = 'Hello, world.' class HelloApp(App): def build(self): return HelloScreen() if __name__ == '__main__': HelloApp().run()
- hello.kv
<HelloScreen>: BoxLayout: orientation: 'vertical' Label: id: label text: root.text Button: id: button text: "Greeting" on_press: root.on_button_click()
- HelloAppからAppを除いた Helloを小文字にした hello.kvが自動で読み込まれます
- hello.kvに記述した<HelloScreen>の名前と同じクラスがレイアウト定義の対象となります
- Labelのtextは、root(HelloScreenクラス)の text(StringProperty)にバインディングします
- Buttonが押されたイベント(on_press)は、root(HelloScreenクラス)のon_button_clickメソッドにバインディングします
PyCharmでKvファイル編集¶
market placeにはプラグインがアップされていませんが、以下からKV Lang File Type Support設定(PyCharm_kv_completion.jar)をダウンロードし、[File]メニュー > [Manage IDE Settings] > [Import Settings]で読み込むと、Kvファイルの編集サポートが利用できます。
https://github.com/Zen-CODE/kivybits/tree/master/IDE
PySimple¶
ライセンス | LGPL |
レイアウトは、上から下へ詰める単純なものです。入れ子のlistで上から下へと、左右方向にウィジェットの配置を指定します。
コード量が少なくGUIを記述できるとされています。
ウィジェットは、Text、Image、InputText、Multiline、Button、CheckBox、Radio、Listbox、Spin、Slider、Frame、VerticalSeparator、ProgressBar、Table、Tree、OptionMenu、Menubar、Canvas、PopupGetText、などです。
レイアウトは、Tab、Pane、Columnなどです。
Hello world¶
import PySimpleGUI as sg
class Application:
KEY_CLICK_GREET = '-GREET-' # ボタンを押した際のイベント定義
KEY_GREETING = '-GREETING-' # あいさつ文表示ウィジェットのユニークID
def __init__(self):
self.text = sg.Text(key=self.KEY_GREETING) # あいさつ文表示ウィジェットTextを生成
self.button = sg.Button('ご挨拶', key=self.KEY_CLICK_GREET) # ボタンウィジェットを生成
self.layout = [[self.text], [self.button]] # レイアウト定義(上下にTextとButton)
self.window = sg.Window('Hello App', self.layout) # トップレベルウィンドウを生成、タイトルとレイアウトを指定
def start(self):
while True: # イベントループ
event, values = self.window.read() # トップレベルウィンドウの中でイベントを待ち、イベントが発生すると復帰
if event == sg.WIN_CLOSED: # イベントがWIN_CLOSEならイベントループを抜ける
break
if event == self.KEY_CLICK_GREET: # イベントがボタン押下(KEY_GREET)ならあいさつ文表示ウィジェットに文字列をセット
self.window[self.KEY_GREETING].Update('Hello, world.')
self.window.close()
if __name__ == '__main__':
application = Application()
application.start()
- レイアウト定義は、多次元リストで上下左右に配置できるので割とシンプルです
- イベントループは自前で記述するので少々大変(柔軟性が高い?)
- イベントループの中で、イベント発生源の識別、操作対象ウィジェットの識別にユニークなIDを定義し使用する必要があり、煩雑