環境
- Windows 10
- Python 3.10.1
- VSCode
使用するソースコード
以下の公開リポジトリに置いています
GitHub - masayan1126/tao-py-py: 作業自動化用 Python ライブラリ
作業自動化用 Python ライブラリ. Contribute to masayan1126/tao-py-py development by creating an account on GitHub.
Tkinterとは?
PythonでGUIを組むことのできるツールキット
動作イメージ
下図のような簡単なランチャーを作成してみたいと思います。ボタンをクリックすると任意のpythonプログラムが実行されます
事前準備
基本的な使用方法
GUIウインドウの作成
- tkinterをインポートして、オブジェクトを作成
- GUIのウインドウタイトルの設定
- ウインドウサイズ(横x縦)の設定
import tkinter
root = tkinter.Tk()
root.title("Window Title")
root.geometry("400x300")
-----具体的な処理の内容はこの中に記載する
root.mainloop()
具体的な実行内容の処理はroot = Tkinter.Tk()とroot.mainloop()の間に記載します
上記のプログラムを実行すると、400px * 300pxのウインドウが表示されます
ラベルの作成
- ラベルを作成し、今日の日付を引数として渡して画面上に表示します
- tkinter.Label(text=)に引数としてラベルに表示する値を指定します
- 部品.pack()とすることで、ウィンドウ上に部品を配置することが可能です
import datetime
・・・割愛
root.geometry("400x300")
today = datetime.date.today()
# ラベル
label = tkinter.Label(text=today)
label.pack()
root.mainloop()
上記のプログラムを実行すると、ウインドウ上に日付のラベルが表示されます
ラベルの配置
上記で作成したラベルをpackメソッドでウインドウの右上に配置します
- packメソッドのanchor引数にtkinter.NEと指定することで、部品を右上に配置することが可能です
- padxで横方向のpaddingを、padyで縦方向のpaddingを指定できます
# ラベル
label = tkinter.Label(text=today)
label.pack(anchor=tkinter.NE, padx=10, pady=5)
anchor一覧
項目 | 内容 |
Tk.CENTER | 中央(デフォルト) |
Tk.W | 左よせ |
Tk.E | 右よせ |
Tk.N | 上よせ |
Tk.S | 下よせ |
Tk.NW | 左上 |
Tk.SW | 左下 |
Tk.NE | 右上 |
Tk.SE | 右下 |
ここまでで、GUIが以下のようになります
import datetime
import tkinter
root = tkinter.Tk()
root.title("Window Title")
root.geometry("700x300")
today = datetime.date.today()
# ラベル
label = tkinter.Label(text=today)
label.pack(anchor=tkinter.NE, padx=10, pady=5)
root.mainloop()
ボタンの作成と配置
- tkinter.Button()でボタンが作成できます
- ボタンオブジェクトは、キー名を指定していろいろな情報を設定できます(ボタン名やクリック時に実行する関数 ※いったん適当に設定)
- grid(配置する列, 配置する行)で該当の部品を配置する場所を指定し、stickyを指定してウィンドウサイズに応じて伸縮するようにします
stickyの設定値
項目 | 内容 |
tk.CENTER | 中央 |
tk.W | 左寄せ |
tk.E | 右寄せ |
tk.N | 上寄せ |
tk.S | 下寄せ |
tk.NW | 左上 |
tk.SW | 左下 |
tk.NE( | 右上 |
tk.SE | 右下 |
各行・列の引き延ばし設定
- 上記のstickyで部品自体の引き延ばしの設定と合わせて、ルート要素(ウィンドウ)に対しても設定を行う必要があります
- 今回のランチャーでは、3*3の構成にしたいので、以下のように設定します
# 各行・列の引き伸ばし設定
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)
root.grid_columnconfigure(2, weight=1)
root.grid_rowconfigure(0, weight=0)
root.grid_rowconfigure(1, weight=1)
root.grid_rowconfigure(2, weight=1)
ここまでで、GUIが以下のようになります
import datetime
import tkinter
root = tkinter.Tk()
root.title("Launcher")
root.geometry("400x200")
frame = tkinter.Frame(root, bg="red")
today = datetime.date.today()
# ラベル
label = tkinter.Label(text=today)
label.grid(column=0, row=0, sticky=tkinter.E, columnspan=3)
# ボタン *6
btn1 = tkinter.Button()
btn1["text"] = "勤怠"
btn1["command"] = root.destroy
btn1.grid(column=0, row=1, sticky="NSEW")
btn2 = tkinter.Button()
btn2["text"] = "②"
btn2["command"] = root.destroy
btn2.grid(column=1, row=1, sticky="NSEW")
btn3 = tkinter.Button()
btn3["text"] = "③"
btn3["command"] = root.destroy
btn3.grid(column=2, row=1, sticky="NSEW")
btn4 = tkinter.Button()
btn4["text"] = "④"
btn4["command"] = root.destroy
btn4.grid(column=0, row=2, sticky="NSEW")
btn5 = tkinter.Button()
btn5["text"] = "⑤"
btn5["command"] = root.destroy
btn5.grid(column=1, row=2, sticky="NSEW")
btn6 = tkinter.Button()
btn6["text"] = "⑥"
btn6["command"] = root.destroy
btn6.grid(column=2, row=2, sticky="NSEW")
# 各列の引き伸ばし設定
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)
root.grid_columnconfigure(2, weight=1)
root.grid_rowconfigure(0, weight=0)
root.grid_rowconfigure(1, weight=1)
root.grid_rowconfigure(2, weight=1)
root.mainloop()
ボタンのクリックイベント
- [“command”]のキーにpythonで定義した関数やメソッドを代入することで、クリックイベントを設定できます
btn1 = tkinter.Button()
btn1["command"] = login.authenticate
login.py
def authenticate():
...割愛
これでクリックイベントが設定できましたのでひととおり完成です。
その他の部品
主なウィジェット一覧
ウィジェット名 | クラス名 | 概要 |
---|---|---|
フレーム | Frame | ウィジェットを格納する枠組みを作る |
ラベル | Label | 文字列やイメージを表示する |
メッセージ | Message | 複数行の文字列を表示する |
ボタン | Button | ボタンを作る |
ラジオボタン | Radiobutton | ラジオボタンを作る |
チェックボタン | Checkbutton | チェックボタンを作る |
リストボックス | Listbox | リストボックスを作る |
スクロールバー | Scrollbar | スクロールバーを作る |
スケール | Scale | スケールを作る |
エントリー | Entry | 1 行の文字列の入力と編集 |
メニュー | Menu | メニューを作る |
メニューボタン | Menubutton | メニューボタンを作る |
ビットマップ | Bitmap | ビットマップを作る |
キャンバス | Canvas | キャンバスを作る |
テキスト | Text | テキストの入力と編集 |
ラベルフレーム | LabelFrame | ラベル付きフレーム |
スピンボックス | Spinbox | スピンボックスを作る |
ペインウィンドウ | PanedWindow | ペインウィンドウを作る |
最終的には以下のようなコードになりました
packages\my_lanchar\main.py
import tkinter
from packages.my_lanchar.lanchar import Lanchar
from shared.Domain.i_widget import IWidget
root = tkinter.Tk()
root.title("Launcher")
root.geometry("400x200")
# パーツの設定
lanchar: IWidget = Lanchar(root=root).build()
root.mainloop()
shared\Domain\i_widget.py
from abc import *
class IWidget(metaclass=ABCMeta):
@abstractmethod
def build(self) -> None:
pass
@abstractmethod
def label(self):
pass
@abstractmethod
def btn(self):
pass
packages\my_lanchar\lanchar.py
import datetime
import tkinter
from typing import Callable, Optional
from packages.jobcan import login
from shared.Domain.i_widget import IWidget
class Lanchar(IWidget):
def __init__(self, root) -> None:
self.root = root
frame = tkinter.Frame(root)
# # 各列の引き伸ばし設定
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)
root.grid_columnconfigure(2, weight=1)
root.grid_rowconfigure(0, weight=0)
root.grid_rowconfigure(1, weight=1)
root.grid_rowconfigure(2, weight=1)
def build(self):
label = self.label(datetime.date.today())
label.grid(column=0, row=0, sticky=tkinter.E, columnspan=3)
# ボタン
btn1 = self.btn("勤怠", login.authenticate)
btn1.grid(column=0, row=1, sticky="NSEW")
btn2 = self.btn("②")
btn2.grid(column=1, row=1, sticky="NSEW")
btn3 = self.btn("③")
btn3.grid(column=2, row=1, sticky="NSEW")
btn4 = self.btn("④")
btn4.grid(column=0, row=2, sticky="NSEW")
btn5 = self.btn("⑤")
btn5.grid(column=1, row=2, sticky="NSEW")
btn6 = self.btn("⑥")
btn6.grid(column=2, row=2, sticky="NSEW")
return self
def label(self, text: str):
return tkinter.Label(text=text)
def btn(self, text: str, command: Optional[Callable] = None):
btn = tkinter.Button()
btn["text"] = text
btn["command"] = command
return btn