如何让Tkinter中Treeview的滚动条与其完全贴合无间距
解决Tkinter Treeview与垂直滚动条视觉间距问题
问题描述
在Tkinter中为Treeview组件添加垂直滚动条时,滚动条与Treeview之间存在明显的视觉间距,无法完全贴合。已尝试将Treeview放入单独框架,但问题仍然存在。
原代码
import tkinter as tk from tkinter import ttk import functions headers = { 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'en-GB,en;q=0.9,en-US;q=0.8,hi;q=0.7,la;q=0.6', 'cache-control': 'no-cache', 'dnt': '1', 'pragma': 'no-cache', 'referer': 'https', 'sec-fetch-mode': 'no-cors', 'sec-fetch-site': 'cross-site', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36' } class View(tk.Tk): def __init__(self, title, size): super().__init__() # main setup self.title(title) self.geometry(f'{size[0]}x{size[1]}') self.resizable(False, False) # create frames self.url_frame = tk.Frame(self) self.url_frame.pack(pady=10) self.tree_frame = tk.Frame(self) self.tree_frame.pack(pady=10) # widgets Widgets(self.url_frame, self.tree_frame) # run self.mainloop() class Widgets: def __init__(self, url_frame, tree_frame): self.product_url_label = ttk.Label(url_frame, text='Product URL:') self.product_url_label.grid(column=0, row=0, padx=20, pady=20, sticky='w') self.product_url_stringvar = tk.StringVar() self.product_url_entry = ttk.Entry(url_frame, textvariable=self.product_url_stringvar, width=70) self.product_url_entry.grid(column=1, row=0, padx=10, columnspan=3, sticky='w') self.run_button = ttk.Button(url_frame, command=self.run_scraper, text='Run') self.run_button.grid(column=4, row=0, padx=20, sticky='w') self.product_label = ttk.Label(tree_frame, text='Product:') self.product_label.grid(column=0, row=0, padx=20, pady=20, sticky='w') self.scroll_bar = ttk.Scrollbar(tree_frame, orient="vertical") self.return_treeview = ttk.Treeview(tree_frame, columns=('ID', 'Date', 'Time', 'Price', 'Change'), yscrollcommand=self.scroll_bar.set) self.return_treeview.column("#0", width=0, stretch=False) self.return_treeview.heading("#0", text="", anchor='center') self.return_treeview.column('ID', anchor='center', width=100) self.return_treeview.heading('ID', text='ID', anchor='center') self.return_treeview.column('Date', anchor='center', width=196) self.return_treeview.heading('Date', text='Date', anchor='center') self.return_treeview.column('Time', anchor='center', width=196) self.return_treeview.heading('Time', text='Time', anchor='center') self.return_treeview.column('Price', anchor='center', width=196) self.return_treeview.heading('Price', text='Price', anchor='center') self.return_treeview.column('Change', anchor='center', width=196) self.return_treeview.heading('Change', text='Change', anchor='center') self.return_treeview.grid(column=0, row=1, columnspan=6, padx=20, sticky='nsew') self.scroll_bar.grid(column=6, row=1, sticky='nsew') self.return_treeview.config(yscrollcommand=self.scroll_bar.set) self.return_treeview.grid_columnconfigure(0, weight=1) def run_scraper(self): url_path = self.product_url_stringvar.get() if not url_path == "": url_data = functions.get_data(url_path, headers) parsed_data = functions.parse_data(url_data) print(parsed_data) else: pass if __name__ == "__main__": View("Coolblue Product Tracker", (950, 400))
解决方案及修改后代码
import tkinter as tk from tkinter import ttk import functions headers = { 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'en-GB,en;q=0.9,en-US;q=0.8,hi;q=0.7,la;q=0.6', 'cache-control': 'no-cache', 'dnt': '1', 'pragma': 'no-cache', 'referer': 'https', 'sec-fetch-mode': 'no-cors', 'sec-fetch-site': 'cross-site', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36' } class View(tk.Tk): def __init__(self, title, size): super().__init__() # main setup self.title(title) self.geometry(f'{size[0]}x{size[1]}') self.resizable(False, False) # create frames self.url_frame = tk.Frame(self) self.url_frame.pack(pady=10) self.tree_frame = tk.Frame(self) self.tree_frame.pack(pady=10, fill='both', expand=True) # widgets Widgets(self.url_frame, self.tree_frame) # run self.mainloop() class Widgets: def __init__(self, url_frame, tree_frame): self.product_url_label = ttk.Label(url_frame, text='Product URL:') self.product_url_label.grid(column=0, row=0, padx=20, pady=20, sticky='w') self.product_url_stringvar = tk.StringVar() self.product_url_entry = ttk.Entry(url_frame, textvariable=self.product_url_stringvar, width=70) self.product_url_entry.grid(column=1, row=0, padx=10, columnspan=3, sticky='w') self.run_button = ttk.Button(url_frame, command=self.run_scraper, text='Run') self.run_button.grid(column=4, row=0, padx=20, sticky='w') self.product_label = ttk.Label(tree_frame, text='Product:') self.product_label.grid(column=0, row=0, padx=20, pady=20, sticky='w') self.scroll_bar = ttk.Scrollbar(tree_frame, orient="vertical") self.return_treeview = ttk.Treeview(tree_frame, columns=('ID', 'Date', 'Time', 'Price', 'Change'), yscrollcommand=self.scroll_bar.set) self.return_treeview.column("#0", width=0, stretch=False) self.return_treeview.heading("#0", text="", anchor='center') self.return_treeview.column('ID', anchor='center', width=100) self.return_treeview.heading('ID', text='ID', anchor='center') self.return_treeview.column('Date', anchor='center', width=196) self.return_treeview.heading('Date', text='Date', anchor='center') self.return_treeview.column('Time', anchor='center', width=196) self.return_treeview.heading('Time', text='Time', anchor='center') self.return_treeview.column('Price', anchor='center', width=196) self.return_treeview.heading('Price', text='Price', anchor='center') self.return_treeview.column('Change', anchor='center', width=196) self.return_treeview.heading('Change', text='Change', anchor='center') # 移除右侧padding,只保留左侧内边距 self.return_treeview.grid(column=0, row=1, padx=(20, 0), sticky='nsew') # 滚动条与Treeview相邻放置 self.scroll_bar.grid(column=1, row=1, sticky='ns') self.scroll_bar.config(command=self.return_treeview.yview) # 配置框架列行权重,让组件占满空间 tree_frame.grid_columnconfigure(0, weight=1) tree_frame.grid_rowconfigure(1, weight=1) def run_scraper(self): url_path = self.product_url_stringvar.get() if not url_path == "": url_data = functions.get_data(url_path, headers) parsed_data = functions.parse_data(url_data) print(parsed_data) else: pass if __name__ == "__main__": View("Coolblue Product Tracker", (950, 400))
关键改动说明
- 调整Treeview内边距:将
padx=20改为padx=(20, 0),只保留左侧内边距,消除右侧多余空隙。 - 滚动条布局优化:将滚动条放在Treeview的相邻列(column=1),替代原跨多列的布局,避免列间距导致的分离。
- 框架权重配置:为tree_frame的第0列设置
weight=1,让Treeview占满水平空间;为第1行设置weight=1,确保组件垂直填充框架。同时给tree_frame的pack添加fill='both', expand=True,让框架适配窗口空间。 - 补全滚动绑定:添加
self.scroll_bar.config(command=self.return_treeview.yview),确保滚动条能控制Treeview的滚动行为。
内容的提问来源于stack exchange,提问作者stilts15
相关产品推荐
相关产品推荐

