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
相关产品推荐
相关产品推荐

