Python Tkinter GUIデモアプリで学ぶ19種ウィジェット完全ガイド|サンプルコード付き (App001)
はじめに
PythonでGUIアプリケーションを作るなら、標準ライブラリの Tkinter が便利です。TkinterはWindows、Mac、Linuxどの環境でも利用でき、軽量かつ学習コストが低いため初心者にもおすすめです。
しかし、Tkinterには多種多様なウィジェット(Entry, Text, Button, Label, Canvasなど)があり、それぞれの特性や使い方を理解するのは簡単ではありません。特に、ユーザーの入力や操作がどのようにGUIに反映されるかを体験するには、サンプルアプリを触るのが最も効果的です。
本記事では、19種類のTkinterウィジェットをまとめた インタラクティブなデモアプリ を紹介します。
各ウィジェットは以下の特徴を備えています:
- 入力や選択がラベルに即時反映(ボタン不要)
- ProgressbarやCanvasにはアニメーションや非同期処理
- NotebookやPanedWindowなども実用例つき
- すべてのウィジェットを1画面で確認可能
記事内では、コード引用、使い方の解説、スクリーンショット挿入ポイント を示し、読者がそのまま実行して学べるようにしています。

サンプルコードを全て表示
import tkinter as tk
from tkinter import ttk, messagebox
import threading
import time
class App001_TkinterWidgets(tk.Tk):
def __init__(self):
super().__init__()
self.title("Tkinter 19 Widgets Demo")
self.geometry("1500x1000")
# top-level layout: categories stacked vertically, each category contains several LabelFrames in a grid
container = ttk.Frame(self, padding=12)
container.pack(fill="both", expand=True)
# Categories and which builders belong to each
categories = {
"Inputs": [self.build_entry, self.build_text, self.build_spinbox, self.build_scale],
"Selections": [self.build_checkbutton, self.build_radiobutton, self.build_listbox, self.build_combobox],
"Displays": [self.build_label, self.build_message, self.build_canvas, self.build_progressbar],
"Views": [self.build_treeview, self.build_notebook, self.build_panedwindow, self.build_labelframe],
"UI Basics": [self.build_button, self.build_separator, self.build_progressbar_async, self.build_scrollbar],
}
# Some builders appear twice above for grouping convenience; ensure unique set of builders for layout
seen = set()
all_builders = []
for group in categories.values():
for b in group:
if b not in seen:
all_builders.append(b)
seen.add(b)
# Layout categories in two columns
col = 0
for i, (cat_name, builders) in enumerate(categories.items()):
frame_cat = ttk.LabelFrame(container, text=cat_name, padding=8)
frame_cat.grid(row=i//2, column=col, padx=8, pady=8, sticky="nsew")
container.columnconfigure(col, weight=1)
col = 1 if col == 0 else 0
# place each builder in the category as a small Labelframe inside
for j, builder in enumerate(builders):
# create inner labelframe titled by builder name
title = builder.__name__.replace('build_', '').replace('_', ' ').capitalize()
inner = ttk.LabelFrame(frame_cat, text=title, padding=6)
inner.grid(row=j//2, column=j%2, padx=6, pady=6, sticky="nsew")
frame_cat.columnconfigure(j%2, weight=1)
# call builder to populate
builder(inner)
# Start a canvas animation used by build_canvas
self.anim_running = True
# ensure proper shutdown
self.protocol("WM_DELETE_WINDOW", self.on_close)
def on_close(self):
self.anim_running = False
self.destroy()
# ----------------------
# BUILDERS (enhanced)
# ----------------------
def build_label(self, parent):
# simple label that other widgets update
self.label_var = tk.StringVar(value="ここに結果が表示されます")
ttk.Label(parent, textvariable=self.label_var).pack()
def build_button(self, parent):
# button updates the shared label
ttk.Button(parent, text="ボタン(ラベル更新)", command=lambda: self.label_var.set("ボタンから更新されました")).pack()
def build_entry(self, parent):
var = tk.StringVar()
ent = ttk.Entry(parent, textvariable=var)
ent.pack()
# auto-reflect via trace
out = ttk.Label(parent, text="入力された値は: ")
out.pack()
def on_change(*args):
out.config(text=f"入力された値は: {var.get()}")
var.trace_add('write', on_change)
def build_text(self, parent):
txt = tk.Text(parent, width=30, height=4)
txt.pack()
out = ttk.Label(parent, text="テキスト内容: ")
out.pack()
# bind key release to update
def on_key(event=None):
out.config(text=f"テキスト内容: {txt.get('1.0', 'end').strip()}")
txt.bind('<KeyRelease>', on_key)
def build_checkbutton(self, parent):
var = tk.BooleanVar(value=False)
cb = ttk.Checkbutton(parent, text="同意する", variable=var)
cb.pack()
out = ttk.Label(parent, text="チェック状態: False")
out.pack()
var.trace_add('write', lambda *a: out.config(text=f"チェック状態: {var.get()}"))
def build_radiobutton(self, parent):
var = tk.StringVar(value='A')
for v in ['A','B','C']:
ttk.Radiobutton(parent, text=v, value=v, variable=var).pack(anchor='w')
out = ttk.Label(parent, text=f"選択: {var.get()}")
out.pack()
var.trace_add('write', lambda *a: out.config(text=f"選択: {var.get()}"))
def build_listbox(self, parent):
lb = tk.Listbox(parent, height=4, exportselection=False)
for item in ['りんご','みかん','ぶどう','バナナ']:
lb.insert(tk.END, item)
lb.pack()
out = ttk.Label(parent, text="選択: ")
out.pack()
def on_select(evt):
sel = lb.curselection()
if sel:
out.config(text=f"選択: {lb.get(sel[0])}")
lb.bind('<<ListboxSelect>>', on_select)
def build_combobox(self, parent):
cb = ttk.Combobox(parent, values=['赤','青','緑'], state='readonly')
cb.current(0)
cb.pack()
out = ttk.Label(parent, text=f"選択: {cb.get()}")
out.pack()
cb.bind('<<ComboboxSelected>>', lambda e: out.config(text=f"選択: {cb.get()}"))
def build_scale(self, parent):
var = tk.DoubleVar(value=50)
sc = ttk.Scale(parent, from_=0, to=100, orient='horizontal', variable=var)
sc.pack(fill='x')
out = ttk.Label(parent, text=f"値: {var.get():.0f}")
out.pack()
# reflect continuously using trace on variable
var.trace_add('write', lambda *a: out.config(text=f"値: {var.get():.0f}"))
def build_spinbox(self, parent):
var = tk.StringVar(value='0')
sp = tk.Spinbox(parent, from_=0, to=20, textvariable=var, width=6)
sp.pack()
out = ttk.Label(parent, text=f"値: {var.get()}")
out.pack()
var.trace_add('write', lambda *a: out.config(text=f"値: {var.get()}"))
def build_progressbar(self, parent):
# determinate progressbar controlled by a Scale (no button)
pb_var = tk.IntVar(value=0)
pb = ttk.Progressbar(parent, maximum=100, variable=pb_var)
pb.pack(fill='x')
scale = ttk.Scale(parent, from_=0, to=100, orient='horizontal', command=lambda v: pb_var.set(int(float(v))))
scale.pack()
out = ttk.Label(parent, text='進捗: 0%')
out.pack()
pb_var.trace_add('write', lambda *a: out.config(text=f"進捗: {pb_var.get()}%"))
def build_progressbar_async(self, parent):
# async progressbar which runs in a background thread and updates via after
pb = ttk.Progressbar(parent, maximum=100, mode='determinate')
pb.pack(fill='x')
out = ttk.Label(parent, text='状態: 停止')
out.pack()
def worker():
out.config(text='状態: 実行中')
for i in range(101):
# schedule UI update on main thread
self.after(0, lambda v=i: pb.configure(value=v))
self.after(0, lambda v=i: out.config(text=f'状態: 実行中 {v}%'))
time.sleep(0.03)
self.after(0, lambda: out.config(text='状態: 完了'))
def start():
threading.Thread(target=worker, daemon=True).start()
ttk.Button(parent, text='非同期開始', command=start).pack()
def build_treeview(self, parent):
tv = ttk.Treeview(parent, columns=('name','age'), show='headings', height=4)
tv.heading('name', text='名前')
tv.heading('age', text='年齢')
tv.insert('', tk.END, values=('田中', 20))
tv.insert('', tk.END, values=('佐藤', 30))
tv.pack()
out = ttk.Label(parent, text='選択: ')
out.pack()
def on_sel(e):
sel = tv.selection()
if sel:
out.config(text=f"選択: {tv.item(sel[0])['values']}")
tv.bind('<<TreeviewSelect>>', on_sel)
def build_canvas(self, parent):
# animated circle that moves horizontally; start/stop controls
c = tk.Canvas(parent, width=260, height=80, bg='white')
c.pack()
oval = c.create_oval(10, 20, 50, 60, fill='orange')
speed_var = tk.IntVar(value=5)
ttk.Scale(parent, from_=1, to=20, variable=speed_var, orient='horizontal').pack()
running = {'on': True}
def animate(pos=0, dir=1):
if not running['on']:
return
w = 260
step = speed_var.get()
pos += step * dir
if pos > w-50:
dir = -1
if pos < 0:
dir = 1
c.coords(oval, pos+10, 20, pos+50, 60)
self.after(50, lambda p=pos, d=dir: animate(p,d))
animate()
def toggle():
running['on'] = not running['on']
if running['on']:
animate()
ttk.Button(parent, text='再開/一時停止', command=toggle).pack()
def build_message(self, parent):
msg = tk.Message(parent, text='これはMessageウィジェットのサンプルです。自動折返しされます。', width=200)
msg.pack()
def build_panedwindow(self, parent):
pw = ttk.PanedWindow(parent, orient="horizontal")
# ttk.Frame は背景色を変えられないため tk.Frame を使用
f1 = tk.Frame(pw, width=100, height=80, bg="red")
f2 = tk.Frame(pw, width=100, height=80, bg="blue")
pw.add(f1)
pw.add(f2)
ttk.Label(f1, text="Left Pane (Red)", background="red", foreground="white").pack()
ttk.Label(f2, text="Right Pane (Blue)", background="blue", foreground="white").pack()
pw.pack(fill="both", expand=True)
def build_separator(self, parent):
ttk.Label(parent, text='上部').pack()
ttk.Separator(parent, orient='horizontal').pack(fill='x', pady=4)
ttk.Label(parent, text='下部').pack()
def build_notebook(self, parent):
# more interactive notebook: tab1 edits a value, tab2 shows live preview
nb = ttk.Notebook(parent)
t1 = ttk.Frame(nb)
t2 = ttk.Frame(nb)
nb.add(t1, text='編集')
nb.add(t2, text='プレビュー')
nb.pack(fill='both', expand=True)
shared_var = tk.StringVar(value='初期テキスト')
ttk.Entry(t1, textvariable=shared_var).pack(pady=4)
ttk.Label(t1, text='ここで入力するとタブ2へ自動反映されます').pack()
lbl = ttk.Label(t2, textvariable=shared_var)
lbl.pack(pady=8)
def build_labelframe(self, parent):
inner = ttk.LabelFrame(parent, text='グループ')
ttk.Label(inner, text='グループ内ラベル').pack()
inner.pack(fill='x')
def build_scrollbar(self, parent):
fr = ttk.Frame(parent)
fr.pack(fill='both')
text = tk.Text(fr, width=30, height=4)
sb = ttk.Scrollbar(fr, orient='vertical', command=text.yview)
text.configure(yscrollcommand=sb.set)
text.pack(side='left', fill='both', expand=True)
sb.pack(side='right', fill='y')
for i in range(20):
text.insert('end', f'行 {i+1}\n')
if __name__ == '__main__':
App001_TkinterWidgets().mainloop()
Python学習に必要なパソコン環境
TkinterでGUIプログラムを学ぶには、パソコンが必須です。
この記事で紹介するデモアプリを動かすにはPython環境が必要で、Windows・Mac・Linuxどの環境でもOKですが、画面サイズや処理速度によって学習効率は大きく変わります。
例えば、ProgressbarのアニメーションやCanvasでの図形描画は、低スペックPCだとカクつきが出る場合があります。
学習を快適に進めるには、性能の良いノートPCやデスクトップが最適です。
これからPythonプログラミングを始める方におすすめのPC例:
[おすすめPCリンク(アフィリエイト用)]
このPCなら軽量で持ち運びやすく、開発環境の構築もスムーズです。デモアプリを試す際にも快適に動作します。
目次
- Entry(文字入力ボックス)
- Text(複数行テキスト入力)
- Spinbox(数値選択)
- Scale(スライダー)
- Checkbutton(チェックボックス)
- Radiobutton(ラジオボタン)
- Listbox(リスト選択)
- Combobox(ドロップダウン選択)
- Label(ラベル表示)
- Button(ボタン操作)
- Progressbar(進捗バー:スライダー連動)
- Progressbar(非同期・スレッド対応)
- Canvas(アニメーション描画)
- Treeview(表形式データ表示)
- Message(複数行メッセージ)
- PanedWindow(左右分割表示)
- Notebook(タブ表示・ライブ反映)
- LabelFrame(グループ化)
- Scrollbar(スクロール付きテキスト)
1. Entry(文字入力ボックス)
Entryウィジェットは、ユーザーが文字列を入力できるGUI部品です。本サンプルでは 入力内容がリアルタイムでラベルに表示 されます。
var = tk.StringVar()
ent = ttk.Entry(parent, textvariable=var)
ent.pack()
out = ttk.Label(parent, text="入力された値は: ")
out.pack()
var.trace_add('write', lambda *a: out.config(text=f"入力された値は: {var.get()}"))ポイント:
StringVarを使用して値を変数として管理trace_add('write', ...)で自動的に入力内容をラベルに反映- 入力後の確認ボタンは不要で即時反映

2. Text(複数行テキスト)
Textウィジェットは、複数行のテキストを扱えるGUI部品です。
サンプルでは キー入力のたびにラベルに内容が反映 されます。
txt = tk.Text(parent, width=30, height=4)
txt.pack()
out = ttk.Label(parent, text="テキスト内容: ")
out.pack()
txt.bind('<KeyRelease>', lambda e: out.config(text=f"テキスト内容: {txt.get('1.0','end').strip()}"))ポイント:
bind('<KeyRelease>')を利用して入力が反映- 複数行の文字を一度に取得できる

3. Spinbox(数値選択)
Spinboxは指定範囲の数値を簡単に選択できるウィジェットです。
var = tk.StringVar(value='0')
sp = tk.Spinbox(parent, from_=0, to=20, textvariable=var)
sp.pack()
out = ttk.Label(parent, text=f"値: {var.get()}")
out.pack()
var.trace_add('write', lambda *a: out.config(text=f"値: {var.get()}"))
ポイント:
- 入力値も選択値もリアルタイムで反映可能
- 設定値の範囲を簡単に制御できる

4. Scale(スライダー)
Scaleはスライダーで数値を選択するウィジェットです。
var = tk.DoubleVar(value=50)
sc = ttk.Scale(parent, from_=0, to=100, orient='horizontal', variable=var)
sc.pack(fill='x')
out = ttk.Label(parent, text=f"値: {var.get():.0f}")
out.pack()
var.trace_add('write', lambda *a: out.config(text=f"値: {var.get():.0f}"))ポイント:
- スライダーの位置がそのまま数値として取得可能
- 変化はリアルタイムでラベルに表示

5. Checkbutton(チェックボックス)
チェックボックスはON/OFFの状態を保持します。
var = tk.BooleanVar(value=False)
cb = ttk.Checkbutton(parent, text="同意する", variable=var)
cb.pack()
out = ttk.Label(parent, text="チェック状態: False")
out.pack()
var.trace_add('write', lambda *a: out.config(text=f"チェック状態: {var.get()}"))ポイント:
- ブール値の管理に最適
- リアルタイムで状態を確認可能

6. Radiobutton(ラジオボタン)
ラジオボタンは複数の選択肢から1つを選ぶ際に使用します。
var = tk.StringVar(value='A')
for v in ['A','B','C']:
ttk.Radiobutton(parent, text=v, value=v, variable=var).pack(anchor='w')
out = ttk.Label(parent, text=f"選択: {var.get()}")
out.pack()
var.trace_add('write', lambda *a: out.config(text=f"選択: {var.get()}"))ポイント:
- 選択肢の変更を即座に反映
- 選択肢が少数の場合、入力フォームや設定画面に最適

7. Listbox(リスト選択)
Listboxは複数の項目の中から1つ(または複数)を選択できるウィジェットです。
lb = tk.Listbox(parent, height=4, exportselection=False)
for item in ['りんご','みかん','ぶどう','バナナ']:
lb.insert(tk.END, item)
lb.pack()
out = ttk.Label(parent, text="選択: ")
out.pack()
lb.bind('<<ListboxSelect>>', lambda e: out.config(text=f"選択: {lb.get(lb.curselection()[0])}" if lb.curselection() else "選択: "))ポイント:
- 選択状態が変わるたびにラベルへ反映
- 複数行リストを管理するUIで有効

8. Combobox(ドロップダウン)
Comboboxは選択肢をドロップダウンで表示できるウィジェットです。
cb = ttk.Combobox(parent, values=['赤','青','緑'], state='readonly')
cb.current(0)
cb.pack()
out = ttk.Label(parent, text=f"選択: {cb.get()}")
out.pack()
cb.bind('<<ComboboxSelected>>', lambda e: out.config(text=f"選択: {cb.get()}"))ポイント:
- ドロップダウン形式で省スペース
- 選択変更がラベルにリアルタイム反映

9. Label(ラベル表示)
Labelはテキスト表示用の最も基本的なウィジェットです。
self.label_var = tk.StringVar(value="ここに結果が表示されます")
ttk.Label(parent, textvariable=self.label_var).pack()ポイント:
- 他のウィジェットの結果表示用として活用
- StringVarを利用すると内容の自動更新が可能

10. Button(ボタン操作)
Buttonはユーザー操作をトリガーするウィジェットです。
ttk.Button(parent, text="ボタン(ラベル更新)", command=lambda: self.label_var.set("ボタンから更新されました")).pack()ポイント:
- 他のウィジェットと組み合わせてイベント駆動型のUIを構築
- ラベルやProgressbarを更新する操作に最適

11. Progressbar(スライダー連動)
スライダー操作に連動する進捗バーです。
pb_var = tk.IntVar(value=0)
pb = ttk.Progressbar(parent, maximum=100, variable=pb_var)
pb.pack(fill='x')
scale = ttk.Scale(parent, from_=0, to=100, orient='horizontal', command=lambda v: pb_var.set(int(float(v))))
scale.pack()
out = ttk.Label(parent, text='進捗: 0%')
out.pack()
pb_var.trace_add('write', lambda *a: out.config(text=f"進捗: {pb_var.get()}%"))ポイント:
- スライダー操作で進捗バーを即時更新
- プログレス表示の理解に最適

12. Progressbar(非同期・スレッド対応)
非同期で進むプログレスバーのサンプルです。
pb = ttk.Progressbar(parent, maximum=100, mode='determinate')
pb.pack(fill='x')
out = ttk.Label(parent, text='状態: 停止')
out.pack()
def worker():
out.config(text='状態: 実行中')
for i in range(101):
self.after(0, lambda v=i: pb.configure(value=v))
self.after(0, lambda v=i: out.config(text=f'状態: 実行中 {v}%'))
time.sleep(0.03)
self.after(0, lambda: out.config(text='状態: 完了'))
ttk.Button(parent, text='非同期開始', command=lambda: threading.Thread(target=worker, daemon=True).start()).pack()ポイント:
threadingを使ってUIを止めずに進行afterでメインスレッドに安全に反映

13. Canvas(アニメーション描画)
Canvasは自由な図形描画やアニメーションが可能です。
c = tk.Canvas(parent, width=260, height=80, bg='white')
c.pack()
oval = c.create_oval(10, 20, 50, 60, fill='orange')
speed_var = tk.IntVar(value=5)
ttk.Scale(parent, from_=1, to=20, variable=speed_var, orient='horizontal').pack()ポイント:
- アニメーションを追加して動的なデモに
- Canvas内の座標を更新して円や矩形を移動


TkinterでGUIアプリを作る際、処理速度や表示の快適さはPCの性能に依存します。
低スペックだと進捗バーのアニメーションやCanvasの描画がカクつく場合もあります。
開発効率を上げて学習をスムーズに進めたい方には、以下のようなPCがおすすめです。
大容量メモリと高速CPUを搭載しているため、複数のウィジェットを使ったデモも快適に動作します。
14. Treeview(表形式表示)
表形式のデータを表示できるウィジェットです。
tv = ttk.Treeview(parent, columns=('name','age'), show='headings', height=4)
tv.heading('name', text='名前')
tv.heading('age', text='年齢')
tv.insert('', tk.END, values=('田中', 20))
tv.insert('', tk.END, values=('佐藤', 30))
tv.pack()
out = ttk.Label(parent, text='選択: ')
out.pack()
tv.bind('<<TreeviewSelect>>', lambda e: out.config(text=f"選択: {tv.item(tv.selection()[0])['values']}" if tv.selection() else '選択: '))ポイント:
- 表形式で複数行・列のデータを管理
- 選択イベントを取得してラベルに反映

15. Message(複数行メッセージ)
Messageは自動折返しテキスト表示に適したウィジェットです。
msg = tk.Message(parent, text='これはMessageウィジェットのサンプルです。自動折返しされます。', width=200)
msg.pack()ポイント:
- 長文テキストの表示に最適
- 自動折返しでレイアウト調整が簡単

16. PanedWindow(左右分割)
左右2ペインを作成可能なウィジェットです。背景色で左右を区別しました。
pw = ttk.PanedWindow(parent, orient="horizontal")
f1 = tk.Frame(pw, width=100, height=80, bg="red")
f2 = tk.Frame(pw, width=100, height=80, bg="blue")
pw.add(f1)
pw.add(f2)
ttk.Label(f1, text="Left Pane (Red)", background="red", foreground="white").pack()
ttk.Label(f2, text="Right Pane (Blue)", background="blue", foreground="white").pack()
pw.pack(fill="both", expand=True)ポイント:
- ドラッグで左右ペインの幅を調整可能
- 背景色で視覚的に区別

17. Notebook(タブ表示・ライブ反映)
Notebookはタブで複数画面を切り替えられます。Tab1の入力をTab2にリアルタイム反映します。
nb = ttk.Notebook(parent)
t1 = ttk.Frame(nb)
t2 = ttk.Frame(nb)
nb.add(t1, text='編集')
nb.add(t2, text='プレビュー')
nb.pack(fill='both', expand=True)
shared_var = tk.StringVar(value='初期テキスト')
ttk.Entry(t1, textvariable=shared_var).pack(pady=4)
ttk.Label(t1, text='入力内容はTab2に自動反映されます').pack()
ttk.Label(t2, textvariable=shared_var).pack(pady=8)ポイント:
- タブ切替で画面を整理
- 同一変数で複数タブに値を反映

18. LabelFrame(グループ化)
LabelFrameはウィジェットをグループ化して見やすくします。
inner = ttk.LabelFrame(parent, text='グループ')
ttk.Label(inner, text='グループ内ラベル').pack()
inner.pack(fill='x')ポイント:
- GUIを整理するためのフレーム
- ラベル付きで視覚的に区切れる

19. Scrollbar(スクロール付きテキスト)
スクロールバー付きTextのサンプルです。
fr = ttk.Frame(parent)
fr.pack(fill='both')
text = tk.Text(fr, width=30, height=4)
sb = ttk.Scrollbar(fr, orient='vertical', command=text.yview)
text.configure(yscrollcommand=sb.set)
text.pack(side='left', fill='both', expand=True)
sb.pack(side='right', fill='y')
for i in range(20):
text.insert('end', f'行 {i+1}\n')ポイント:
- 長文や大量データの表示に必要
- ScrollbarとTextを連動させる

おわりに
本記事では Python Tkinter GUIデモアプリ を用いて、19種類のウィジェットを紹介しました。
リアルタイム反映やアニメーション、非同期処理などの体験により、初心者でも直感的にGUI作成を学べます。
このサンプルアプリを使えば、Tkinterの基本操作から応用まで 短時間で学習可能 です。

PythonでGUIプログラムを学ぶなら、パソコンは必須です。
Tkinterのデモアプリを動かすにはPython環境が必要で、WindowsでもMacでも動作します。
私自身もこのサンプルを試す際に、性能の良いノートPCを使うことで快適に学習できました。
もしこれからPythonプログラミングを始めるなら、以下のPCがおすすめです。軽量で持ち運びやすく、開発環境の構築もスムーズです。
おすすめPCはこちら:

コメントを残す