Masayan tech blog.

  1. ブログ記事一覧>
  2. 【Tkinter】Pythonでデスクトップアプリを作成する方法

【Tkinter】Pythonでデスクトップアプリを作成する方法

公開日

環境

  • Windows 10
  • Python 3.10.1
  • VSCode

Tkinterとは?

PythonでGUIを組むことのできるツールキット

GUI化することにより、Pythonスクリプトファイルをコンソール等から直接実行しなくてもよくなります。

動作イメージ

下図のような簡単なランチャーを作成してみたいと思います。ボタンをクリックすると任意のpythonプログラムが実行されます

事前準備

Tkinterは通常は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()

今日の日付は、datetimeモジュールで簡単に生成することが可能です

上記のプログラムを実行すると、ウインドウ上に日付のラベルが表示されます

ラベルの配置

上記で作成したラベルをpackメソッドでウインドウの右上に配置します

部品の配置のためのメソッドには、大きく分けてpack, place, gridの3パターンがあります

# ラベル
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を指定してウィンドウサイズに応じて伸縮するようにします

部品の均等配置には、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)

weightを使用することにより、余白を配分するときの割合を数値で指定することができます(重みづけ)

ここまでで、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(): ...割愛

commandに指定する関数には()は不要です。付与してしまうとウィンドウを起動したタイミングで関数が実行されてしまいます。

これでクリックイベントが設定できましたのでひととおり完成です。

その他の部品

主なウィジェット一覧

ウィジェット名

クラス名

概要

フレーム

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

Tkinterへの依存度を下げるために、インターフェースを作成し、それを実装する形で構築しています

まとめ

いかがでしたでしょうか。本記事では、Tkinterを使用してPythonでデスクトップアプリを作成する方法について紹介しています。Tkinterを使用すると簡単にデスクトップアプリを作成できますのでぜひ試してみてください。