4日目のゴール
4日目のテーマは
「ボタンとGUI部品を“きれいに並べて”、アプリらしい画面を作る」 ことです。
ここまでであなたはすでに、
ウィンドウを出せる
ボタンを押して関数を呼べる
Entry から入力を受け取って、ラベルに表示できる
というところまで来ています。
4日目では一歩進んで、
部品を「縦に積むだけ」から卒業するgrid を使って、行と列でレイアウトする
ボタン・ラベル・Entry を“意味のある配置”にする
という、「見た目もちゃんとしたGUI」の入り口に入ります。
pack だけだと、だんだんつらくなる理由
縦に積むだけだと「フォーム」が作りにくい
3日目までのコードは、だいたいこうでした。
label_name.pack()
entry_name.pack()
label_like.pack()
entry_like.pack()
button.pack()
label_result.pack()
Pythonこれはこれでシンプルで良いのですが、
例えばこんな画面を作りたくなったらどうでしょう。
「名前: [ ]」
「年齢: [ ]」
「好きなもの: [ ]」
というように、
ラベルと入力欄を横に並べたい。
pack() だけでこれをやろうとすると、
急に難易度が上がります。
そこで登場するのが、
「行と列で部品を配置する grid」 です。
grid の基本を押さえる
行(row)と列(column)で考える
grid は、
「表(テーブル)」をイメージすると分かりやすいです。
1行目・0列目にラベル
1行目・1列目にEntry
2行目・0列目にラベル
2行目・1列目にEntry
というように、
「どの行・どの列に置くか」を指定していきます。
まずは、名前と年齢を入力する簡単なフォームをgrid で作ってみましょう。
import tkinter as tk
root = tk.Tk()
root.title("gridの基本")
label_name = tk.Label(root, text="名前:")
entry_name = tk.Entry(root)
label_age = tk.Label(root, text="年齢:")
entry_age = tk.Entry(root)
label_name.grid(row=0, column=0)
entry_name.grid(row=0, column=1)
label_age.grid(row=1, column=0)
entry_age.grid(row=1, column=1)
root.mainloop()
Pythonここでの重要ポイントは、
grid(row=行番号, column=列番号) で配置する
行と列は 0 から始まる(0行目、1行目…)
ということです。
pack と grid は「同じ親の中で混ぜない」
これをやるとエラーになる
ひとつだけ、かなり大事なルールがあります。
同じウィンドウ(同じ親)に対して、pack と grid を混ぜて使ってはいけない。
例えば、これはダメです。
label_name = tk.Label(root, text="名前:")
label_name.pack()
entry_name = tk.Entry(root)
entry_name.grid(row=0, column=1) # ← 同じ root に pack と grid を混ぜている
Pythonこうすると、実行時にエラーが出ます。
対策はシンプルで、
「同じ親の中では、pack か grid のどちらかに統一する」
と覚えておけばOKです。
後で出てくる Frame を使うと、
「この枠の中は grid」「この枠の中は pack」
といった使い分けもできますが、
4日目ではまず「混ぜない」というルールだけ意識しておきましょう。
grid で「フォーム+ボタン+結果表示」を作る
3日目の自己紹介アプリを grid 版にする
3日目で作った「自己紹介メッセージメーカー」を、grid でレイアウトし直してみます。
import tkinter as tk
def on_make_message():
name = entry_name.get().strip()
like = entry_like.get().strip()
if name == "" or like == "":
label_result.config(text="名前と好きなものを両方入力してください。")
return
message = f"私は{name}です。{like}が好きです。"
label_result.config(text=message)
root = tk.Tk()
root.title("自己紹介メッセージメーカー(grid版)")
label_name = tk.Label(root, text="名前:")
entry_name = tk.Entry(root)
label_like = tk.Label(root, text="好きなもの:")
entry_like = tk.Entry(root)
button = tk.Button(root, text="メッセージを作る", command=on_make_message)
label_result = tk.Label(root, text="ここにメッセージが表示されます")
label_name.grid(row=0, column=0, padx=5, pady=5, sticky="e")
entry_name.grid(row=0, column=1, padx=5, pady=5)
label_like.grid(row=1, column=0, padx=5, pady=5, sticky="e")
entry_like.grid(row=1, column=1, padx=5, pady=5)
button.grid(row=2, column=0, columnspan=2, pady=10)
label_result.grid(row=3, column=0, columnspan=2, pady=10)
root.mainloop()
Pythonここで新しく出てきたものを、丁寧に見ていきます。
grid のオプションを深掘りする
padding(余白)を付ける padx, pady
padx と pady は、
「部品の周りの余白」を指定します。
padx=5 は左右に5ピクセルの余白pady=5 は上下に5ピクセルの余白
です。
これを付けるだけで、
ぎゅうぎゅう詰めの画面から、
少し余裕のある見た目になります。
sticky で「どの方向にくっつけるか」を決める
sticky は、
「セル(マス)の中で、どの方向に寄せるか」を指定します。
sticky="e" は east(東)=右寄せsticky="w" は west(西)=左寄せsticky="n" は north(北)=上寄せsticky="s" は south(南)=下寄せ
複数組み合わせることもできます。
sticky="we" なら左右に広がるsticky="ns" なら上下に広がるsticky="nsew" なら四方向に広がる
今回のコードでは、
label_name.grid(..., sticky="e")
Pythonとして、
ラベルを「右寄せ」にしています。
これにより、
「名前: [ ]」
「好きなもの: [ ]」
のように、
ラベルが入力欄の右側にぴったり寄ってくれます。
columnspan で「列をまたぐ」
columnspan は、
「この部品を、何列分にまたがって表示するか」
を指定します。
button.grid(row=2, column=0, columnspan=2)
Pythonこれは、
「2行目の0列目から始めて、2列分を占有する」
という意味です。
今回のレイアウトでは、
0列目:ラベル
1列目:Entry
という構成なので、
ボタンや結果ラベルは「画面の横幅いっぱい」にしたくてcolumnspan=2 にしています。
Frame で「まとまり」を作る
画面を“箱”で分けるイメージ
少しだけレベルを上げて、Frame という部品を紹介します。
Frame は、
「他の部品を入れるための“箱”」
だと思ってください。
例えば、
上のエリア:入力フォーム
下のエリア:結果表示
というように、
画面をざっくり2つのエリアに分けたいときに使えます。
Frame を使った構成の例
import tkinter as tk
def on_make_message():
name = entry_name.get().strip()
like = entry_like.get().strip()
if name == "" or like == "":
label_result.config(text="名前と好きなものを両方入力してください。")
return
message = f"私は{name}です。{like}が好きです。"
label_result.config(text=message)
root = tk.Tk()
root.title("Frameでエリア分け")
frame_form = tk.Frame(root)
frame_form.pack(padx=10, pady=10)
frame_result = tk.Frame(root)
frame_result.pack(padx=10, pady=10)
label_name = tk.Label(frame_form, text="名前:")
entry_name = tk.Entry(frame_form)
label_like = tk.Label(frame_form, text="好きなもの:")
entry_like = tk.Entry(frame_form)
button = tk.Button(frame_form, text="メッセージを作る", command=on_make_message)
label_result = tk.Label(frame_result, text="ここにメッセージが表示されます")
label_name.grid(row=0, column=0, padx=5, pady=5, sticky="e")
entry_name.grid(row=0, column=1, padx=5, pady=5)
label_like.grid(row=1, column=0, padx=5, pady=5, sticky="e")
entry_like.grid(row=1, column=1, padx=5, pady=5)
button.grid(row=2, column=0, columnspan=2, pady=10)
label_result.pack()
root.mainloop()
Pythonここでの構造を整理すると、
root の上に frame_form と frame_result を pack で縦に並べるframe_form の中では grid を使ってフォームを組むframe_result の中では pack でラベルを置く
という形になっています。
大事なのは、
「親が違えば、pack と grid を使い分けていい」
ということです。
同じ親の中で混ぜるのはNGですが、Frame で親を分ければ、
レイアウトの自由度が一気に上がります。
4日目のミニアプリ:簡易ログイン画面(見た目だけ)
仕様
ユーザー名とパスワードを入力するフォーム
「ログイン」ボタン
結果を表示するラベル
レイアウトは grid で整える
中身の認証処理はまだやらず、
「見た目とボタンイベント」に集中します。
コード
import tkinter as tk
def on_login_click():
username = entry_user.get().strip()
password = entry_pass.get().strip()
if username == "" or password == "":
label_result.config(text="ユーザー名とパスワードを入力してください。")
return
label_result.config(text=f"{username} さんとしてログインを試みました。(ダミー)")
root = tk.Tk()
root.title("ログイン画面(ダミー)")
frame_form = tk.Frame(root)
frame_form.pack(padx=10, pady=10)
frame_result = tk.Frame(root)
frame_result.pack(padx=10, pady=10)
label_user = tk.Label(frame_form, text="ユーザー名:")
entry_user = tk.Entry(frame_form)
label_pass = tk.Label(frame_form, text="パスワード:")
entry_pass = tk.Entry(frame_form, show="*")
button_login = tk.Button(frame_form, text="ログイン", command=on_login_click)
label_user.grid(row=0, column=0, padx=5, pady=5, sticky="e")
entry_user.grid(row=0, column=1, padx=5, pady=5)
label_pass.grid(row=1, column=0, padx=5, pady=5, sticky="e")
entry_pass.grid(row=1, column=1, padx=5, pady=5)
button_login.grid(row=2, column=0, columnspan=2, pady=10)
label_result = tk.Label(frame_result, text="ここに結果が表示されます")
label_result.pack()
root.mainloop()
Pythonここで新しく出てきた show="*" は、
パスワード入力欄でよくある「●●●」表示をするためのものです。
Entry に show="*" を付けると、
入力した文字がそのまま見えず、
指定した文字(ここでは *)で表示されます。
4日目で絶対に押さえてほしい本質
「どこに何を置くか」を意識した瞬間、アプリは“それっぽく”なる
今日いちばん大事なのは、
GUIは「部品を並べる」だけでなく
「どこに何を置くか」を設計する世界
だという感覚です。
そのための道具が、
行と列で配置する grid
部品のまとまりを作る Frame
余白を付ける padx / pady
セルの中での位置を決める sticky
複数列にまたがる columnspan
といった要素たちです。
1〜3日目で学んだ
ボタンイベント
Entry からの入力
ラベルへの表示
に、今日の「レイアウトの基礎」を組み合わせると、
一気に「アプリっぽい画面」になります。
5日目以降は、
チェックボックス、ラジオボタン、リストボックスなどを足して、
「選択」「状態」「複数データ」を扱う方向に進んでいきます。
まずは今日のログイン画面を、自分なりに
ボタンを増やす(キャンセルボタンなど)
ラベルの位置や余白を変える
Frame を増やしてエリアを分ける
など、少しずついじって、
「レイアウトを自分でコントロールする感覚」を掴んでみてください。

