はじめに
PythonでGUIアプリを作りたいとき、多くの開発者が最初に出会うのがTkinterです。しかし、デフォルトのTkinterは見た目が古く感じることも。そこで注目されているのがCustomTkinterです。
この記事では、標準のTkinterとモダンなCustomTkinterを比較しながら、実際にGUIアプリを作成する方法を解説します。
Tkinterとは
TkinterはPythonの標準ライブラリに含まれるGUIツールキットです。
メリット:
- 標準ライブラリなので追加インストール不要
- 軽量で高速
- 豊富な情報とサンプルコード
デメリット:
- デザインが古く見える
- モダンなUIを作るには工夫が必要
CustomTkinterとは
CustomTkinterは、TkinterをベースにしたモダンなデザインのGUIライブラリです。
メリット:
- モダンで美しいデザイン
- ダークモード対応
- Tkinterの知識がそのまま活用可能
デメリット:
- 追加インストールが必要
- 比較的新しいライブラリ
インストール
CustomTkinterを使用する場合は、pipでインストールします:
pip install customtkinter
電卓アプリを作ってみよう
同じ機能の電卓アプリを、TkinterとCustomTkinterの両方で作成して比較してみます。
標準Tkinter版
import tkinter as tk
from tkinter import ttk
class Calculator:
def __init__(self):
self.root = tk.Tk()
self.root.title("電卓 - Tkinter")
self.root.geometry("300x400")
# 計算式を保存する変数
self.equation = ""
# 結果表示用のEntry
self.result_var = tk.StringVar()
self.result_var.set("0")
self.create_widgets()
def create_widgets(self):
# 結果表示エリア
result_frame = tk.Frame(self.root)
result_frame.pack(pady=10, padx=10, fill='x')
result_entry = tk.Entry(
result_frame,
textvariable=self.result_var,
font=('Arial', 16),
justify='right',
state='readonly'
)
result_entry.pack(fill='x')
# ボタンエリア
button_frame = tk.Frame(self.root)
button_frame.pack(pady=10, padx=10, fill='both', expand=True)
# ボタンの配置
buttons = [
['C', '±', '%', '÷'],
['7', '8', '9', '×'],
['4', '5', '6', '-'],
['1', '2', '3', '+'],
['0', '.', '', '=']
]
for i, row in enumerate(buttons):
for j, text in enumerate(row):
if text == '=':
btn = tk.Button(
button_frame, text=text,
font=('Arial', 14),
bg='orange',
command=self.calculate
)
btn.grid(row=i, column=3, sticky='nsew', padx=2, pady=2)
elif text == '':
# 空の要素はスキップ
continue
else:
btn = tk.Button(
button_frame, text=text,
font=('Arial', 14),
command=lambda t=text: self.button_click(t)
)
btn.grid(row=i, column=j, sticky='nsew', padx=2, pady=2)
# グリッドの重みを設定
for i in range(5):
button_frame.rowconfigure(i, weight=1)
for j in range(4):
button_frame.columnconfigure(j, weight=1)
def button_click(self, char):
if char == 'C':
self.equation = ""
self.result_var.set("0")
elif char == '±':
if self.equation and self.equation[-1].isdigit():
self.equation = str(-float(self.equation))
self.result_var.set(self.equation)
else:
if char in '×÷':
char = '*' if char == '×' else '/'
self.equation += str(char)
self.result_var.set(self.equation)
def calculate(self):
try:
result = eval(self.equation)
self.result_var.set(str(result))
self.equation = str(result)
except:
self.result_var.set("Error")
self.equation = ""
def run(self):
self.root.mainloop()
if __name__ == "__main__":
calc = Calculator()
calc.run()
CustomTkinter版
import customtkinter as ctk
class ModernCalculator:
def __init__(self):
# テーマ設定
ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("blue")
self.root = ctk.CTk()
self.root.title("電卓 - CustomTkinter")
self.root.geometry("300x400")
self.equation = ""
self.create_widgets()
def create_widgets(self):
# 結果表示エリア
self.result_var = ctk.StringVar(value="0")
result_entry = ctk.CTkEntry(
self.root,
textvariable=self.result_var,
font=ctk.CTkFont(size=20, weight="bold"),
justify='right',
state='readonly',
height=50
)
result_entry.pack(pady=20, padx=20, fill='x')
# ボタンエリア
button_frame = ctk.CTkFrame(self.root)
button_frame.pack(pady=10, padx=20, fill='both', expand=True)
# ボタンの配置
buttons = [
['C', '±', '%', '÷'],
['7', '8', '9', '×'],
['4', '5', '6', '-'],
['1', '2', '3', '+'],
['0', '.', '', '=']
]
for i, row in enumerate(buttons):
for j, text in enumerate(row):
if text == '=':
btn = ctk.CTkButton(
button_frame, text=text,
font=ctk.CTkFont(size=16, weight="bold"),
command=self.calculate,
fg_color="orange",
hover_color="darkorange",
width=50, height=50
)
btn.grid(row=i, column=3, sticky='ew', padx=5, pady=5)
elif text == '':
# 空の要素はスキップ
continue
elif text in ['÷', '×', '-', '+']:
btn = ctk.CTkButton(
button_frame, text=text,
font=ctk.CTkFont(size=16, weight="bold"),
command=lambda t=text: self.button_click(t),
fg_color="gray30",
hover_color="gray40",
width=50, height=50
)
btn.grid(row=i, column=j, sticky='ew', padx=5, pady=5)
else:
btn = ctk.CTkButton(
button_frame, text=text,
font=ctk.CTkFont(size=16, weight="bold"),
command=lambda t=text: self.button_click(t),
width=50, height=50
)
btn.grid(row=i, column=j, sticky='ew', padx=5, pady=5)
# グリッドの重みを設定
for i in range(5):
button_frame.rowconfigure(i, weight=1)
for j in range(4):
button_frame.columnconfigure(j, weight=1)
def button_click(self, char):
if char == 'C':
self.equation = ""
self.result_var.set("0")
elif char == '±':
if self.equation and self.equation[-1].isdigit():
self.equation = str(-float(self.equation))
self.result_var.set(self.equation)
else:
if char in '×÷':
char = '*' if char == '×' else '/'
self.equation += str(char)
self.result_var.set(self.equation)
def calculate(self):
try:
result = eval(self.equation)
self.result_var.set(str(result))
self.equation = str(result)
except:
self.result_var.set("Error")
self.equation = ""
def run(self):
self.root.mainloop()
if __name__ == "__main__":
calc = ModernCalculator()
calc.run()
どちらを選ぶべきか
Tkinterは軽量で追加ライブラリ不要なため、シンプルで軽いアプリに向きます。
CustomTkinterはモダンなデザインや標準のダークモード対応が魅力で、ユーザー体験を重視するアプリに適しています。
サンプルコードの注意点
今回のコードはデモの実装として紹介していますが、以下の課題があります:
コードの±機能: 記事中の±ボタンの実装は不完全
eval()の使用: セキュリティ上の問題
ちゃんとした実装にするには、適切な数式パーサーの使用やより堅牢なエラーハンドリングが必要です。
まとめ
TkinterとCustomTkinterは、それぞれ異なる特徴を持つGUIライブラリです。プロジェクトの要件に応じて適切に選択することで、効率的にGUIアプリケーションを開発できます。
モダンなデザインを求める場合はCustomTkinter、軽量性を重視する場合はTkinterを選択するのが良いでしょう。どちらもPythonでGUIアプリを作成する優秀な選択肢です。
参考資料
この記事がPython GUIアプリ開発の参考になれば幸いです。ぜひ実際にコードを試してみてください!