はじめに
Pythonの標準ライブラリに含まれるGUIライブラリのTkinterを使っていて、「Frameウィジェットをスクロールしたい!」というタイミングで少しハマったので、まとめます。
コピペしてすぐに動作確認可能なサンプルコードを載せています。
Frameウィジェット
Frameウィジェットは、LabelやButtonを配置することで複雑なウィジェットを構築することが可能です。
Scrollbarウィジェット
Tkinterのいくつかのウィジェットは、Scrollbarウィジェットを取り付けることで、ウィンドウより大きな仮想領域にビューをスライドできるようになります。
FrameにScrollbarを直接取り付けることはできない
TkinterでScrollbarを直接取り付ける(Scrollbarの親ウィジェットとして設定する)ことが可能なウィジェットの例は、以下です。
- Canvas
- Listbox
- Entry
- Spinbox
- Text
...そう、FrameにScrollbarを直接取り付けることはできないのです。
これはTkinterの仕様です。
じゃあどうするのか
FrameをCanvasに埋め込み、そのCanvasにScrollbarを取り付けることで、Frameをスクロールしているように見せることができます。
Scrollbarが実際にスクロールする対象は、Canvasです。
以下、コピペしてすぐに動作確認可能なサンプルコードです。
import tkinter as tk
root = tk.Tk()
root.geometry("900x600")
canvas = tk.Canvas(root)
frame = tk.Frame(canvas)
# Canvasを親とした縦方向のScrollbar
scrollbar = tk.Scrollbar(
canvas, orient=tk.VERTICAL, command=canvas.yview
)
# Frameを親とした動作確認用のLabel
label = tk.Label(frame, text="動作確認用ラベル")
# スクロールの設定
canvas.configure(scrollregion=(0, 0, 900, 900))
canvas.configure(yscrollcommand=scrollbar.set)
# 諸々を配置
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
canvas.pack(expand=True, fill=tk.BOTH)
label.pack(expand=1)
# Canvas上の座標(0, 0)に対してFrameの左上(nw=north-west)をあてがうように、Frameを埋め込む
canvas.create_window((0, 0), window=frame, anchor="nw", width=900, height=900)
root.mainloop()
Canvasクラスのcreate_window()メソッドにより、Canvasに他のウィジェットを埋め込むことができます。
埋め込むウィジェットの実体は、Canvas Window オブジェクトといいます。
Canvasに埋め込んだウィジェットは、Canvasのスクロールと連携してスクロールします。