You need to enable JavaScript to run this app. Tkinter电子表格查看器滚动及窗口自适应填充问题咨询
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter电子表格查看器滚动及窗口自适应填充问题咨询

问题根因
  • 根窗口行权重分配错误,控制栏和内容区各占一半高度,且内容区没有配置向下拉伸的属性
  • 自定义的NewFrame、NewCanvas方法中权重配置对象错误,应该给父容器配置子控件所在行列的权重,而非给新生成的控件自身配置
  • 垂直滚动画布绑定的内部窗口对象错误,绑定了外层的vsFrame而非存放数据的botFrame
  • 多层级容器的sticky属性配置不全,无法自适应填满父容器空间
修复后完整代码
import tkinter as tk
from tkinter import messagebox

def NewFrame(parent,d,ro = 0, co = 0, st = "NEWS", w = 1):
    fr = tk.Frame(parent, **d)
    fr.grid(row=ro,column=co, sticky=st)
    # 改为给父容器配置对应行列的权重
    parent.grid_columnconfigure(co, weight=w)
    parent.grid_rowconfigure(ro, weight=w)
    return fr

def NewCanvas(parent,d,ro = 0, co = 0, st = "NEWS", w = 1):
    ca = tk.Canvas(parent, **d)
    ca.grid(row=ro,column=co, sticky=st)
    # 改为给父容器配置对应行列的权重
    parent.grid_columnconfigure(co, weight=w)
    parent.grid_rowconfigure(ro, weight=w)
    return ca

class test:
    def __init__(self,root,hxw):
        self.hxw=hxw
        root.wm_title("Test")
        root.configure(bd=2)
        root.configure(background="black")
        root.grid_columnconfigure(0, weight=1)
        # 控制栏不需要拉伸,weight设为0,内容区weight设为1占满剩余高度
        root.grid_rowconfigure(0, weight=0)
        root.grid_rowconfigure(1, weight=1)
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        if not self.hxw:
            self.hxw='{0:d}x{1:d}+{2:d}+{3:d}'.format(min(940,screen_width),min(560,screen_height),int(screen_width/3),int(screen_height/3))
        root.geometry(self.hxw) #Width x Height
        root.update()
        self.top = root
        self.topFrame = NewFrame(self.top, {'height':25, 'background':"blue"}, st="NEW") 
        tk.Button(self.topFrame, text="Help", command=self.callback4).grid(row=0, column=0, sticky='E')
        # 修改sticky为NEWS,让内容区占满根窗口剩余空间
        self.hsFrame = NewFrame(self.top, {'background':"red"}, st="NEWS", ro=1)
        # hcanvas占满hsFrame除滚动条外的空间
        self.hsFrame.grid_rowconfigure(0, weight=1)
        self.hsFrame.grid_rowconfigure(2, weight=0)
        self.hcanvas = NewCanvas(self.hsFrame, {'background':"green"}, st="NEWS", ro=0)
        self.mFrame = tk.Frame(self.hcanvas)

        self.mFrame.bind(
            "<Configure>",
            lambda e: self.hcanvas.configure(
                scrollregion=self.hcanvas.bbox("all")
            )
        )

        self.hcanvas.create_window((0, 0), window=self.mFrame, anchor="nw")

        # 创建水平滚动条
        hsbar = tk.Scrollbar(self.hsFrame, orient=tk.HORIZONTAL, command=self.hcanvas.xview)
        hsbar.grid(row=2, column=0, sticky=tk.EW)
        self.hcanvas.configure(xscrollcommand=hsbar.set)

        # 列头不拉伸,数据区占满剩余高度
        self.mFrame.grid_rowconfigure(0, weight=0)
        self.mFrame.grid_rowconfigure(1, weight=1)
        self.mFrame.grid_columnconfigure(0, weight=1)
        self.labelFrame = NewFrame(self.mFrame, {'background':"grey", 'height':25}, ro=0, st="NEW")
        for col in range(20):
            tkl = tk.Label(self.labelFrame, width=20, borderwidth="1", relief="solid", text=("col %d" % (col+1)))
            tkl.grid(row=0, column=col, sticky='news')
            self.labelFrame.grid_columnconfigure(col,weight=1)

        self.vsFrame = NewFrame(self.mFrame, {'background':"yellow"}, ro=1, st="NEWS") 
        # vsFrame布局:左侧画布占满空间,右侧放垂直滚动条
        self.vsFrame.grid_columnconfigure(0, weight=1)
        self.vsFrame.grid_columnconfigure(1, weight=0)
        self.vsFrame.grid_rowconfigure(0, weight=1)
        self.vcanvas = NewCanvas(self.vsFrame, {'background':"#ff00ff"}, ro=0, co=0, st="NEWS")

        self.botFrame = tk.Frame(self.vcanvas, background="orange")

        self.botFrame.bind(
            "<Configure>",
            lambda e: self.vcanvas.configure(
                scrollregion=self.vcanvas.bbox("all")
            )
        )

        # 修复:vcanvas绑定存放数据的botFrame作为内部滚动窗口
        self.vcanvas.create_window((0, 0), window=self.botFrame, anchor="nw")

        # 创建垂直滚动条
        self.vsbar = tk.Scrollbar(self.vsFrame, orient=tk.VERTICAL, command=self.vcanvas.yview)
        self.vsbar.grid(row=0, column=1, sticky=tk.NS)
        self.vcanvas.configure(yscrollcommand=self.vsbar.set)

        # 生成50行20列测试数据
        rows = 50
        columns = 20
        for i in range(0, rows):
            tkl = tk.Label(self.botFrame, width=10, borderwidth="1", relief="solid", text=("%d,%d" % (i+1, 1)))
            tkl.grid(row=i, column=0, sticky='news')
            self.botFrame.grid_rowconfigure(i, weight=1)
            for j in range(1, columns):
                tkl = tk.Label(self.botFrame, width=10, borderwidth="1", relief="solid", text=("%d,%d" % (i+1, j+1)))
                tkl.grid(row=i, column=j, sticky='news')
                self.botFrame.grid_columnconfigure(j, weight=1)

    def callback4(self):
        print('root', root.winfo_geometry())
        print('self.topFrame', self.topFrame.winfo_geometry())
        print('self.hsFrame', self.hsFrame.winfo_geometry())
        print('self.hcanvas', self.hcanvas.winfo_geometry())
        print('self.mFrame', self.mFrame.winfo_geometry())
        print('self.labelFrame', self.labelFrame.winfo_geometry())
        print('self.vsFrame', self.vsFrame.winfo_geometry())
        print('self.vcanvas', self.vcanvas.winfo_geometry())
        print('self.botFrame', self.botFrame.winfo_geometry())
        print('------------------------------')
        messagebox.showinfo(
            "help",
            "This is help"
            )


# 启动GUI
root = tk.Tk()
test(root,None)
root.mainloop()
修复效果说明
  • 顶部控制栏固定不滚动
  • 列头和数据区同步水平滚动
  • 数据区支持双向滚动,右侧显示垂直滚动条
  • 底部显示水平滚动条,整个界面自适应填满窗口
  • 所有数据内容正常渲染显示

内容的提问来源于stack exchange,提问作者user2801282

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 23:48:04