最近幾天在用 Tinker 開發公司維運軟體時發現了幾個過去不曾注意的小問題, 但這些細節卻足以讓我耗掉無謂的時間在 debug 上面, 例如要幫 Treview 綁定一個右捲軸時, 捲軸居然出現在 Treeview 下方而不是右方, 重新檢視 API 說明與比對之前成功範例都沒錯啊, 怪了.
後來我將原始碼貼給 ChatGPT 詢問到底問題出在哪裡, 原來正解是 : 捲軸必須在 TreeView 之前放置 (pack), 亦即要先呼叫捲軸的 pack(), 然後再呼叫 TreeView 的 pack(), 範例如下 :
測試 1 : 正確的 Treeview + Scrollbar 用法 :
import tkinter as tk
from tkinter import ttk
# 建立視窗
root=tk.Tk() # 建立視窗物件
root.title('TreeView 與 Scrollbar 測試') # 設定視窗標題
root.geometry('600x200') # 設定視窗尺寸
# 建立捲軸與 Treeview
scrollbar=tk.Scrollbar(root) # 建立捲軸物件
scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # 卷軸必須比 Treeview 先放置
treeview=ttk.Treeview(root, columns=('country', 'continent')) # 建立 Treeview
treeview.heading('#0', text='國碼') # 設定 icon 欄標題
treeview.heading('#1', text='國家') # 設定第二欄標題
treeview.heading('#2', text='洲別') # 設定第三欄標題
# 設定 Treeview 內容 : text 是 icon 欄位, vales 是其他欄位
treeview.insert('', index=tk.END, text='81', values=['日本', '亞洲'])
treeview.insert('', index=tk.END, text='31', values=['荷蘭', '歐洲'])
treeview.insert('', index=tk.END, text='249', values=['蘇丹', '非洲'])
treeview.insert('', index=tk.END, text='886', values=['台灣', '亞洲'])
treeview.insert('', index=tk.END, text='65', values=['新加坡', '亞洲'])
treeview.insert('', index=tk.END, text='44', values=['英國', '歐洲'])
treeview.insert('', index=tk.END, text='501', values=['貝里斯', '美洲'])
treeview.insert('', index=tk.END, text='66', values=['泰國', '亞洲'])
treeview.insert('', index=tk.END, text='504', values=['宏都拉斯', '美洲'])
treeview.insert('', index=tk.END, text='850', values=['北韓', '亞洲'])
treeview.pack(fill=tk.BOTH, expand=True) # Treeview 須在捲軸後放置
# 捲軸與 Treeview 互相綁定
treeview.config(yscrollcommand=scrollbar.set) # Treeview 綁定右捲軸
scrollbar.config(command=treeview.yview) # 捲軸綁定 Treeview
root.mainloop()
注意此處的關鍵在於 Scrollbar 須比 Treeview 先放到 root 容器中, 結果如下 :
可見捲軸正確地出現在 Treeview 右邊. 如果 pack() 的順序顛倒, 即先放 Treeview 後放 Scrollbar, 那麼 Scrollbar 會出現在 Treeview 下方, 例如 :
測試 1 : 不正確的 Treeview + Scrollbar 用法 :
import tkinter as tk
from tkinter import ttk
# 建立視窗
root=tk.Tk() # 建立視窗物件
root.title('TreeView 與 Scrollbar 測試') # 設定視窗標題
root.geometry('600x300') # 設定視窗尺寸
# 建立捲軸與 Treeview
treeview=ttk.Treeview(root, columns=('country', 'continent')) # 建立 Treeview
treeview.heading('#0', text='國碼') # 設定 icon 欄標題
treeview.heading('#1', text='國家') # 設定第二欄標題
treeview.heading('#2', text='洲別') # 設定第三欄標題
# 設定 Treeview 內容 : text 是 icon 欄位, vales 是其他欄位
treeview.insert('', index=tk.END, text='81', values=['日本', '亞洲'])
treeview.insert('', index=tk.END, text='31', values=['荷蘭', '歐洲'])
treeview.insert('', index=tk.END, text='249', values=['蘇丹', '非洲'])
treeview.insert('', index=tk.END, text='886', values=['台灣', '亞洲'])
treeview.insert('', index=tk.END, text='65', values=['新加坡', '亞洲'])
treeview.insert('', index=tk.END, text='44', values=['英國', '歐洲'])
treeview.insert('', index=tk.END, text='501', values=['貝里斯', '美洲'])
treeview.insert('', index=tk.END, text='66', values=['泰國', '亞洲'])
treeview.insert('', index=tk.END, text='504', values=['宏都拉斯', '美洲'])
treeview.insert('', index=tk.END, text='850', values=['北韓', '亞洲'])
treeview.pack(fill=tk.BOTH, expand=True) # Treeview 須在捲軸後放置
scrollbar=tk.Scrollbar(root) # 建立捲軸物件
scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # 卷軸比 Treeview 後放置會出現在下方
treeview.config(yscrollcommand=scrollbar.set) # Treeview 綁定右捲軸
scrollbar.config(command=treeview.yview) # 捲軸綁定 Treeview
root.mainloop()
此例程式碼內容與上面完全相同, 差別僅在於 Scrollbar 呼叫 pack() 順序在 Treeview 呼叫 pack() 之後, 結果捲軸會被放在 Treeview 下方, 如下圖所示 :
順序決定了位置, 人生也是如此.
沒有留言:
張貼留言