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

Tkinter框架切换故障:button_5无法跳转至PageOne

问题描述

使用Tkinter-Designer将Figma框架转换为Python代码并整合到StartPage类中,参考框架切换的实现代码后,点击button_5无法跳转至PageOne,无任何视觉反馈。本人不熟悉OOP,求定位问题原因。

完整代码如下:

import tkinter as tk                # python 3
from tkinter import font as tkfont  # python 3

from pathlib import Path
OUTPUT_PATH = Path(__file__).parent
ASSETS_PATH = OUTPUT_PATH / Path(r"Z:\python\projects\v\code\gui\tmp\TkinterDesigner\build\assets\frame0")

def relative_to_assets(path: str) -> Path:
    return ASSETS_PATH / Path(path)


class SampleApp(tk.Tk):

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

        self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (StartPage, PageOne, PageTwo):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame

            # put all of the pages in the same location;
            # the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("StartPage")

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


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        canvas = tk.Canvas(
            bg="#FFFFFF",
            height=724,
            width=1056,
            bd=0,
            highlightthickness=0,
            relief="ridge"
        )

        canvas.place(x=0, y=0)
        canvas.create_rectangle(
            56.0,
            68.0,
            954.0,
            673.0,
            fill="#F2F2F2",
            outline="")

        canvas.create_rectangle(
            56.0,
            68.0,
            285.0,
            673.0,
            fill="#D4D3D3",
            outline="")

        self.button_image_1 = tk.PhotoImage(
            file=relative_to_assets("button_1.png"))
        button_1 = tk.Button(
            image=self.button_image_1,
            borderwidth=0,
            highlightthickness=0,
            command=lambda: print("button_1 clicked"),
            relief="flat"
        )
        button_1.place(
            x=56.0,
            y=348.0,
            width=229.0,
            height=37.0
        )

        self.button_image_2 = tk.PhotoImage(
            file=relative_to_assets("button_2.png"))
        button_2 = tk.Button(
            image=self.button_image_2,
            borderwidth=0,
            highlightthickness=0,
            command=lambda: print("button_2 clicked"),
            relief="flat"
        )
        button_2.place(
            x=56.0,
            y=312.0,
            width=229.0,
            height=37.0
        )

        self.button_image_3 = tk.PhotoImage(
            file=relative_to_assets("button_3.png"))
        button_3 = tk.Button(
            image=self.button_image_3,
            borderwidth=0,
            highlightthickness=0,
            command=lambda: print("button_3 clicked"),
            relief="flat"
        )
        button_3.place(
            x=56.0,
            y=274.0,
            width=229.0,
            height=36.0
        )

        self.button_image_4 = tk.PhotoImage(
            file=relative_to_assets("button_4.png"))
        button_4 = tk.Button(
            image=self.button_image_4,
            borderwidth=0,
            highlightthickness=0,
            command=lambda: print("button_4 clicked"),
            relief="flat"
        )
        button_4.place(
            x=56.0,
            y=239.0,
            width=229.0,
            height=36.0
        )

        self.button_image_5 = tk.PhotoImage(
            file=relative_to_assets("button_5.png"))
        button_5 = tk.Button(
            image=self.button_image_5,
            borderwidth=0,
            highlightthickness=0,
            command=lambda: controller.show_frame("PageOne"),
            relief="flat"
        )
        button_5.place(
            x=56.0,
            y=201.0,
            width=229.0,
            height=37.0
        )

        self.image_image_1 = tk.PhotoImage(
            file=relative_to_assets("image_1.png"))
        image_1 = canvas.create_image(
            617.0,
            300.0,
            image=self.image_image_1
        )

        canvas.create_text(
            706.0,
            574.0,
            anchor="nw",
            text="         -Jim Rohn",
            fill="#000000",
            font=("RobotoMono Regular", 14 * -1)
        )

        canvas.create_text(
            433.0,
            500.0,
            anchor="nw",
            text="“Reading is essential for those who seek to rise above the ordinary.” ",
            fill="#000000",
            font=("RobotoMono Regular", 14 * -1)
        )

        canvas.create_text(
            84.0,
            100.0,
            anchor="nw",
            text="Hello ZZZ!",
            fill="#000000",
            font=("RobotoMono Bold", 18 * -1)
        )


class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is page 1", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Go to the start page",
                           command=lambda: controller.show_frame("StartPage"))
        button.pack()


class PageTwo(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is page 2", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Go to the start page",
                           command=lambda: controller.show_frame("StartPage"))
        button.pack()


if __name__ == "__main__":
    app = SampleApp()
    app.geometry("1056x724")
    app.configure(bg="#FFFFFF")
    app.mainloop()
问题原因

button_5的点击逻辑本身没有问题,框架切换操作已经执行了,但**StartPage中的Canvas使用了place(x=0, y=0)绝对定位,它会脱离StartPage的布局层级,直接显示在主窗口的最上层**,导致切换后的PageOne被这个Canvas遮挡,视觉上看不到变化。

修复方案

将Canvas的布局方式从place改为pack,让它作为StartPage的子组件,跟随StartPage的显示/隐藏一起变化:

修改StartPage类中Canvas的布局代码:

# 替换原来的 canvas.place(x=0, y=0)
canvas.pack(fill="both", expand=True)

同时,移除Canvas的固定宽高设置,让它自动适配StartPage的大小(可选,让布局更灵活):

canvas = tk.Canvas(
    self,
    bg="#FFFFFF",
    # 移除固定height和width
    bd=0,
    highlightthickness=0,
    relief="ridge"
)

修改后,StartPage的Canvas会作为Frame的一部分,当切换到PageOne时,StartPage被隐藏,Canvas也会跟着隐藏,PageOne的内容就能正常显示了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 11:10:15