使用grid_propagate(False)时Tkinter Frame高度始终为1的问题
问题描述
- 基于
tkscrolledframe.ScrolledFrame实现StockFrame类,在内部的mainFrame上设置grid_propagate(False)后,若不手动指定height属性,Frame高度会固定为1像素;手动设置固定height则会出现大量可滚动的空白区域。 - 后续尝试通过
updateHeight方法动态获取并设置mainFrame高度:先开启grid_propagate(True),获取所需高度后再关闭并设置该高度。但程序首次运行时出现可向上滚动的异常,点击按钮后恢复正常。
相关代码
gui.py
from .stock import getFruitStockInParalel, getTimeTillRestock from tkscrolledframe import ScrolledFrame import tkinter as tk class StockFrame(ScrolledFrame): BG = "#90A4AE" def __init__(self, master, **kw): super().__init__(master, **kw) # 创建变量 self.lVisible = False self.blVisible = False self.cFruitLabels = list() self.lFruitLabels = list() self.blFruitLabels = list() self.cFruits = list() self.lFruits = list() self.blFruits = list() self.cFruits, self.lFruits, self.blFruits = getFruitStockInParalel() # 在父ScrolledFrame内创建Frame self.mainFrame = self.display_widget(tk.Frame, fit_width=True) self.mainFrame.config(borderwidth=3, background=self.BG) self.mainFrame.grid_propagate(False) self.mainFrame.columnconfigure(0, weight=1, uniform="stockframe") self.mainFrame.columnconfigure(1, weight=1, uniform="stockframe") # 创建并放置显示补货倒计时的Label self.timeTillRestockLabel = tk.Label(self.mainFrame, text="", anchor=tk.W, font=("Segoe UI", 10), bg="white", relief="ridge", borderwidth=2, padx=5, pady=2) self.timeTillRestockLabel.grid(row=0, column=0, sticky=tk.W+tk.E, padx=6, columnspan=2, pady=5) # 创建并放置切换上一次及上上次库存的按钮 self.lButton = tk.Button(self.mainFrame, text="Toggle Last Stock", command=self.toggleLastStock, padx=100, bg="white") self.lButton.grid(row=100, columnspan=2, column=0, padx=7, pady=0, sticky=tk.W) self.blButton = tk.Button(self.mainFrame, text="Toggle Before Last Stock", command=self.toggleBlastStock, padx=100, bg="white") self.blButton.grid(row=102, columnspan=2, column=0, padx=7, pady=(5,0), sticky=tk.W) # 创建lFrame和blFrame self.lFrame = tk.Frame(self.mainFrame, bg=self.BG) self.lFrame.columnconfigure(0, weight=1, uniform="lframe") self.lFrame.columnconfigure(1, weight=1, uniform="lframe") self.blFrame = tk.Frame(self.mainFrame, bg=self.BG) self.blFrame.columnconfigure(0, weight=1, uniform="blframe") self.blFrame.columnconfigure(1, weight=1, uniform="blframe") # 启动循环 self.mainLoop() self.timeRemainingLoop() # 循环方法 def mainLoop(self): self.updateCurrentFruits() self.updatelFrame() self.updateblFrame() self.bindAllToScrollWheel(self) self.after(60*5*1000, self.mainLoop) def timeRemainingLoop(self): self.timeTillRestockLabel.config(text="Time till restock: "+str(getTimeTillRestock()).split(".")[0]) self.after(1, self.timeRemainingLoop) def bindAllToScrollWheel(self, parent): # 递归绑定父组件内所有控件到滚轮 for widget in parent.winfo_children(): self.bindAllToScrollWheel(widget) self.bind_scroll_wheel(parent) # 水果标签更新方法 def updateCurrentFruits(self): # 销毁旧的水果标签 for fl in self.cFruitLabels: fl.destroy() self.cFruitLabels.clear() # 创建新的水果标签并布局 for fruit in self.cFruits: self.cFruitLabels.append(fruitLabel(self.mainFrame, fruit.name, usePrice=True)) for i, fl in enumerate(self.cFruitLabels): fl.grid(row=(i//2)+1, column=int((not i%2 == 0)), pady=(0,5)) def updatelFrame(self): # 销毁lFrame内旧的水果标签 for fl in self.lFruitLabels: fl.destroy() self.lFruitLabels.clear() # 创建新的水果标签并布局 for fruit in self.lFruits: self.lFruitLabels.append(fruitLabel(self.lFrame, fruit.name, usePrice=True)) for i, fl in enumerate(self.lFruitLabels): fl.grid(row=(i//2)+1, column=int((not i%2 == 0)), padx=7, pady=(5,1)) def updateblFrame(self): # 销毁blFrame内旧的水果标签 for fl in self.blFruitLabels: fl.destroy() self.blFruitLabels.clear() # 创建新的水果标签并布局 for fruit in self.blFruits: self.blFruitLabels.append(fruitLabel(self.blFrame, fruit.name, usePrice=True)) for i, fl in enumerate(self.blFruitLabels): fl.grid(row=(i//2)+1, column=int((not i%2 == 0)), padx=7, pady=(5,1)) # 切换库存显示方法 def toggleLastStock(self): if not self.lVisible: self.lVisible = True self.lFrame.grid(row=101, column=0, columnspan=2, sticky=tk.W) elif self.lVisible: self.lVisible = False self.lFrame.grid_forget() def toggleBlastStock(self): if not self.blVisible: self.blVisible = True self.blFrame.grid(row=103, column=0, columnspan=2, sticky=tk.W) elif self.blVisible: self.blVisible = False self.blFrame.grid_forget()
fruitLabel是一个根据水果名称返回包含多个组件的Frame的函数,经测试功能正常。
main.py
import tkinter as tk from scripts.gui import * from scripts.value import saveFruitValues # Segoe UI # 90A4AE # 创建主窗口 root = tk.Tk() root.geometry("900x800") root.iconbitmap("assets/kitsune.ico") root.title("Blox Fruits") root.resizable(0,0) # 启动时更新水果价值 saveFruitValues() stockFrame = StockFrame(root, relief="solid", scrollbars="vertical", width=200) stockFrame.grid(column=0, row=0, sticky=tk.N + tk.W + tk.S) root.columnconfigure(0, weight=1) root.rowconfigure(0, weight=1) root.update_idletasks() root.mainloop()
新增的updateHeight方法及修改后的mainLoop
def updateHeight(self): # 更新mainFrame高度 self.mainFrame.grid_propagate(True) self.mainFrame.update_idletasks() reqHeight = self.mainFrame.winfo_reqheight() if reqHeight < self.winfo_height(): reqHeight = self.winfo_height() self.mainFrame.grid_propagate(False) self.mainFrame.config(height=reqHeight)
def mainLoop(self): self.updateCurrentFruits() self.updatelFrame() self.updateblFrame() self.updateHeight() self.bindAllToScrollWheel(self) self.after(60*5*1000, self.mainLoop)
内容的提问来源于stack exchange,提问作者Mews
相关产品推荐
相关产品推荐

