You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:29:50