2016-10-20 4 views
-1

Таким образом, с помощью приведенного ниже кода я могу переключать страницы с Страница 1 на страницу2, Page2 в страницу3, Page3 на страницу4, но не может перейти от Page4 к странице1.Python tkinter - невозможно отобразить один и тот же кадр более одного раза?

Он отображает сообщение об ошибке:

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 

мне было интересно, если это потому, что я не могу переключиться на тот же кадр более, что когда-то, или я просто делаю что-то неправильно. если я поместил все классы на одну и ту же страницу, это, кажется, исправить проблему, но я хотел бы иметь все классы на отдельных страницах. Может быть, это связано с импортом страниц? Это упрощенная версия моего кода, чтобы помочь показать проблему:

CCTV:

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() 

Page1:

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) 

Page2:

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) 

Page3:

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) 

Page4:

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) 
+0

Возможно, вы забыли 'из Page1 import *' Или вы импортируете неправильную страницу. – furas

+0

Лучше всего написать все классы, связанные с страницами, в одном файле: 'pages.py', а не так много разных/Возможно, вы не импортировали' Page1' в файл 'Page4.py'. ум, показывающий содержимое 'Page4'. –

+0

Если все страницы почти идентичны, вы можете создать один класс «BasePage» и использовать его для определения других классов - «class Page1 (BasePage)». – furas

ответ

1

Там нет хорошего способа, чтобы исправить свой код, как написано - у вас есть круговой импорт, который я откровенно удивленные работы на всех. Когда вы импортируете Page1 в основную программу, это приводит к тому, что Page2 импортируется, потому что Page1 импортирует его. Это приводит к тому, что Page3 импортируется, потому что Page2 импортирует его. Это приводит к тому, что page4 импортируется, потому что импортирует его. Затем ваша основная программа явно импортирует 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

+0

Да, это работает, спасибо. – Conor

1

Импортированный модуль запускается только один раз, каждый подключенный файл, который импортирует его, использует одну и ту же копию модуля. Поэтому в случае импорта цикла (импорт A в B, импорт B в C, импорт C в A), он будет испорчен и не будет признан во второй раз. Для e.г: У вас есть файл A.py:

from B import b 
from C import c 

print (b, c) # this is fine 

и содержание B.py будет:

Это будет возвращать ошибку:

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") 
+0

Спасибо, что объяснили причину ошибки импорта. Теперь я понимаю :) – Conor

Смежные вопросы