Python tkinter不能多次显示同一帧?

2024-10-02 08:29:18 发布

您现在位置:Python中文网/ 问答频道 /正文

使用下面的代码,我可以将页面从第1页切换到第2页,从第2页切换到第3页,从第3页切换到第4页,但不能从第4页切换到第1页。你知道吗

它显示错误消息:

Traceback (most recent call last):
  File "C:\Python33\lib\tkinter\__init__.py", line 1489, in __call__
    return self.func(*args)
  File "F:\CCTV\test\Page4.py", line 29, in buttonLoginClicked
    self.controller.show_frame(Page1)
NameError: global name 'Page1' is not defined

我想知道这是不是因为我不能切换到同一帧多次或我只是做错了什么。如果我把所有的类放在同一个页面上,似乎可以解决这个问题,但是我希望所有的类都放在不同的页面上。也许这和导入页面有关?这是我的代码的简化版本,有助于显示问题:

中央电视台:

import tkinter as tk
from tkinter import ttk, messagebox
from Page1 import *
from Page2 import *
from Page3 import *
from Page4 import *

class CCTV(tk.Tk):

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

        container = tk.Frame(self)
        container.pack()
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (Page1, Page2, Page3, Page4):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(column=0, row=0, sticky="nsew")

        self.openPage()

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

    def openPage(self):
        self.show_frame(Page1)

app = CCTV()
app.geometry("800x600")
app.mainloop()

第1页:

import tkinter as tk
from tkinter import ttk, messagebox
from Page2 import *

class Page1(tk.Frame):

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

    def createView(self):
        inner_frame = tk.Frame(self)
        inner_frame.pack(side="top", fill="none")

        self.labelTitle = ttk.Label(inner_frame, text="Page 1")
        self.buttonLogin = ttk.Button(inner_frame, text="Page 2", command=self.buttonLoginClicked)

        self.labelTitle.grid(row=1, columnspan=4, pady=10)
        self.buttonLogin.grid(row=2, columnspan=4, pady=10)

        self.grid_rowconfigure(0, weight=1)
        self.grid_rowconfigure(3, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(3, weight=1)


    def buttonLoginClicked(self):
        self.controller.show_frame(Page2)

第2页:

import tkinter as tk
from tkinter import ttk, messagebox
from Page3 import *

class Page2(tk.Frame):

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

    def createView(self):
        inner_frame = tk.Frame(self)
        inner_frame.pack(side="top", fill="none")

        self.labelTitle = ttk.Label(inner_frame, text="Page 2")
        self.buttonLogin = ttk.Button(inner_frame, text="Page 3", command=self.buttonLoginClicked)

        self.labelTitle.grid(row=1, columnspan=4, pady=10)
        self.buttonLogin.grid(row=2, columnspan=4, pady=10)

        self.grid_rowconfigure(0, weight=1)
        self.grid_rowconfigure(3, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(3, weight=1)


    def buttonLoginClicked(self):
        self.controller.show_frame(Page3)

第3页:

import tkinter as tk
from tkinter import ttk, messagebox
from Page4 import *

class Page3(tk.Frame):

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

    def createView(self):
        inner_frame = tk.Frame(self)
        inner_frame.pack(side="top", fill="none")

        self.labelTitle = ttk.Label(inner_frame, text="Page 3")
        self.buttonLogin = ttk.Button(inner_frame, text="Page 4", command=self.buttonLoginClicked)

        self.labelTitle.grid(row=1, columnspan=4, pady=10)
        self.buttonLogin.grid(row=2, columnspan=4, pady=10)

        self.grid_rowconfigure(0, weight=1)
        self.grid_rowconfigure(3, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(3, weight=1)


    def buttonLoginClicked(self):
        self.controller.show_frame(Page4)

第4页:

import tkinter as tk
from tkinter import ttk, messagebox
from Page1 import *

class Page4(tk.Frame):

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

    def createView(self):
        inner_frame = tk.Frame(self)
        inner_frame.pack(side="top", fill="none")

        self.labelTitle = ttk.Label(inner_frame, text="Page 4")
        self.buttonLogin = ttk.Button(inner_frame, text="Page 1", command=self.buttonLoginClicked)

        self.labelTitle.grid(row=1, columnspan=4, pady=10)
        self.buttonLogin.grid(row=2, columnspan=4, pady=10)

        self.grid_rowconfigure(0, weight=1)
        self.grid_rowconfigure(3, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(3, weight=1)


    def buttonLoginClicked(self):
        self.controller.show_frame(Page1)

Tags: fromimportselfinittkinterdefframetk
2条回答

导入的模块只运行一次,导入该模块的每个连接文件共享该模块的同一副本。因此,如果循环导入(B中导入A,C中导入B,A中导入C),它将被弄乱,并且不会被第二次识别。 例如: 您有文件A.py

from B import b
from C import c

print (b, c) # this is fine

B.py的内容是:

from C import c # not proper initialization as it has already been in A.py already
print (c)

将返回一个错误:

global name 'c' is not defined

问题是导入的文件将是相同的副本,因此您不能实际导入不同连接文件中的同一模块,您可以做的是:

pages = { 
          Page1: Page2,
          Page2: Page3,
          Page3: Page4,
          Page4: Page1
      }
for F, goto_page in pages.items():
  frame = F(container, self, goto_page)
  self.frames[F] = frame
  frame.grid(column=0, row=0, sticky="nsew")

没有好的方法来修复你的代码,因为你有循环导入,坦白说,我很惊讶的工作在所有。当您在主程序中导入Page1时,它会导致Page2被导入,因为Page1导入了它。这导致Page3被导入,因为Page2导入了它。这导致Page4被导入,因为Page3导入了它。然后主程序显式导入Page2,这会导致再次导入Page3,这会导致再次导入Page4,依此类推。你知道吗

问题的根源是您需要导入一个页面才能切换到它。别那么做。相反,可以重新定义show_frame以获取页面的名称,这样就不必为了切换到页面而导入页面(当然,除了在主程序中)。你知道吗

简短的版本在这里。请注意,代码获取页面名称并将其用作字典键:

class CCTV(tk.Tk):
    def __init__(...):
        ...
        for F in (Page1, Page2, Page3, Page4):
            page_name = F.__name__
            frame = F(container, self)
            self.frames[page_name] = frame
            ...

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

这样,只需执行以下操作即可切换到帧而无需导入:

self.controller.show_frame("Page1")

完整的工作示例如下:https://stackoverflow.com/a/7557028/7432

相关问题 更多 >

    热门问题