概要
CustomTkinter(および素の tkinter)で GUI を組んでいると、pack() と grid() を同じ親ウィジェットの中で混ぜて使ったときに _tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack というエラーで落ちることがあります。CustomTkinter の入門記事を書く過程で確認した、定番だけど地味にハマるポイントなので原因と直し方をまとめます。
つまずいたポイント
次のように、同じ親(app)に対して pack() と grid() を両方呼ぶとエラーになります。
import customtkinter as ctk
app = ctk.CTk()
app.geometry("300x200")
label = ctk.CTkLabel(app, text="上のラベル")
label.pack(pady=10)
entry = ctk.CTkEntry(app)
entry.grid(row=0, column=0) # 同じ親(app)に grid を混ぜると…
app.mainloop()
_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack
pack と grid は tkinter の「ジオメトリマネージャ」と呼ばれる配置の仕組みで、同じ親の中では1種類しか使えません。片方をやめてどちらかに統一する必要がある、というエラーです。
対策: 親を分ける(内側だけ別のFrameにする)
ただし「1つの画面全体で1種類しか使えない」わけではありません。親を分ければ、pack と grid を共存させられます。 外側の大枠は pack で組み、その中に置いた Frame の中だけ grid で組む、というのがよくあるパターンです。
import customtkinter as ctk
app = ctk.CTk()
app.geometry("300x200")
label = ctk.CTkLabel(app, text="上のラベル")
label.pack(pady=10) # 外側は pack で組む
form = ctk.CTkFrame(app)
form.pack(pady=10) # Frame自体はpackでappに置く
ctk.CTkLabel(form, text="名前:").grid(row=0, column=0, padx=5)
ctk.CTkEntry(form).grid(row=0, column=1, padx=5) # Frameの中だけgridでOK
app.mainloop()
form(Frame)の中では grid だけを使い、form 自身は親の app に対して pack で配置しています。親子で担当を分けることで、両方の配置方式のいいところを1画面の中で使い分けられます。
完全なソースコードと手順はブログにまとめています
CustomTkinter のインストール手順、CTkLabel/CTkButton/CTkEntry など基本部品の使い方、pack/grid それぞれの詳しい使い方、ダークモード対応(set_appearance_mode)、tkinter との違いの比較表まで、以下の記事に書いています。