You need to enable JavaScript to run this app. Tkinter用类与tkraise()切换Frame时如何固定为600×400(偏好Grid)
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter用类与tkraise()切换Frame时如何固定为600×400(偏好Grid)

问题根源

Tkinter Frame默认开启几何传播机制,会自动根据内部子组件的总大小调整自身尺寸,哪怕初始化时指定了width/height参数,只要不关闭该机制,Frame就会被内容撑开。另外原代码中创建的container容器没有被用作页面Frame的父组件,属于冗余代码,没有起到约束尺寸的作用。

修复方案

全程遵循Grid布局要求,无需使用Pack,改动点如下:

  • 在每个页面Frame的初始化逻辑中,添加self.grid_propagate(False),强制关闭几何传播,让Frame保持固定尺寸。
  • 移除无用的container代码,主窗口和页面Frame的布局统一使用Grid,无需使用place。
  • 移除模糊导入(from tkinter import *、from tkinter.ttk import *),统一用tk.xxx显式调用组件,避免tk和ttk组件的尺寸计算冲突。
修复后代码
import tkinter as tk
from tkinter import font as tkfont
from PIL import ImageTk, Image


class InterimMain(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # 主窗口尺寸与居中配置
        window_width = 800
        window_height = 600
        position_right = int(self.winfo_screenwidth()/2 - window_width/2)
        position_down = int(self.winfo_screenheight()/2 - window_height/2)
        self.geometry(f"{window_width}x{window_height}+{position_right}+{position_down}")

        # 主窗口Grid配置,让页面Frame居中
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (WelcomeScreen, Login):
            page_name = F.__name__
            frame = F(parent=self, controller=self)
            self.frames[page_name] = frame
            # Grid布局放置堆叠的页面Frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("WelcomeScreen")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()


class WelcomeScreen(tk.Frame):
    def __init__(self, parent, controller):
        # 初始化固定尺寸的Frame
        tk.Frame.__init__(self, parent, width=600, height=400)
        # 关闭几何传播,禁止被内部内容撑开
        self.grid_propagate(False)
        
        tk.Label(self,text="WELCOME TO THE INTRIM REPORT",font=("Arial Bold",16)).grid(row=0, pady=20)
        load = Image.open("logo2.jpg")
        render = ImageTk.PhotoImage(load)
        
        img = tk.Label(self, image=render)
        img.image = render # 保留图片引用,避免被GC回收
        img.grid(row=1)
        
        tk.Label(self,text="Press the button to proceed",font=("Arial Bold",10)).grid(row=2, padx=5, pady=10)
        tk.Button(self,text="Sign In",font=("Arial Bold",16),command=lambda: controller.show_frame("Login")).grid(row=3, padx=20, pady=20)
        

class Login(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, width=600, height=400)
        self.grid_propagate(False)
        self.config(background="blue")

        tk.Label(self,text="LOGIN SCREEN",font=("Arial Bold",16)).grid(row=0,column=0,pady=10,columnspan=3)
        tk.Label(self,text="Username",font=("Arial",12)).grid(row=1,column=0,sticky='w')
        tk.Label(self,text="Password",font=("Arial",12)).grid(row=2,column=0,sticky='w')
        
        user = tk.Entry(self)
        pwd = tk.Entry(self)
        user.grid(row=1,column=1,pady=5,columnspan=2,sticky='we')
        pwd.grid(row=2,column=1,pady=5,columnspan=2,sticky='we')
        
        # 补充原代码缺失的checkLogin占位逻辑
        def checkLogin(u, p):
            pass
        tk.Button(self,text="LOGIN",command=lambda: checkLogin(user.get(), pwd.get())).grid(row=3,column=2,columnspan=3,sticky='e')


if __name__ == "__main__":
    app = InterimMain()
    app.mainloop()
注意事项
  • grid_propagate(False)是核心逻辑,启用后Frame会严格保持你设置的600×400尺寸,不会被内部子组件撑开。
  • 主窗口的grid_rowconfigure/grid_columnconfigure配置了weight=1,是为了让堆叠的页面Frame自动居中,完全没有使用Pack布局。
  • 必须保留图片的引用赋值(img.image = render),否则Tkinter的垃圾回收机制会自动销毁图片资源,导致图片无法显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.14 09:15:05