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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 23:54:51