2016-09-20 3 views
-1

Привет, у меня есть код из ответа на Switch between two frames in tkinter, который я пытаюсь изменить, поэтому кнопка в классе StartPage может вызывать функцию msg в классе PageOne.Функция вызова Tkinter в другом классе

Но им получать эту ошибку:

AttributeError: 'Frame' object has no attribute 'msg'

Вот код до сих пор я наметил изменения, которые я сделал в коде.

import tkinter as tk # python3 
#import Tkinter as tk # python 

TITLE_FONT = ("Helvetica", 18, "bold") 

class SampleApp(tk.Tk): 

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

     # 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 

     self.parent = parent #<-- my mod 

     label = tk.Label(self, text="This is the start page", font=TITLE_FONT) 
     label.pack(side="top", fill="x", pady=10) 

     button1 = tk.Button(self, text="Go to Page One", 
          command=lambda: controller.show_frame("PageOne")) 
     button2 = tk.Button(self, text="Go to Page Two", 
          command=lambda: controller.show_frame("PageTwo")) 
     self.button3 = tk.Button(text='Calling msg in another class', command=self.parent.msg)#<-- my mod 
     button1.pack() 
     button2.pack() 
     button3.pack()#<-- my mod 

class PageOne(tk.Frame): 

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

     self.parent = parent #<-- my mod 

     label = tk.Label(self, text="This is page 1", font=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() 

    def msg(self): #<-- my mod 
     print("IT WORKS!!") 

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=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.mainloop() 

Может ли кто-нибудь помочь мне?

+1

Вы сделали 'container = tk.Frame (self)', поэтому 'container' является' Frame', а затем вы передаете это как 'parent' в следующем цикле. Это означает, что 'self.parent' является ссылкой на базовый' Frame', который не имеет вашего дополнительного метода msg, а не ваших расширенных подклассов. – TigerhawkT3

+0

Я не понимаю. И что же мне делать? –

ответ

0

Поскольку вы создаете все классы в цикле, самый простой способ добавить ссылки между ними - это, вероятно, сделать это после этого цикла. Удалите эти ссылки из класса, так как они не будут действительны до момента создания экземпляра. Обратите внимание, как button3 больше не создается или не упаковывается в StartPage, а скорее в SampleApp.

for F in (StartPage, PageOne, PageTwo): 
    ... 

self.frames['StartPage'].pageone = self.frames['PageOne'] 
self.frames['StartPage'].button3 = tk.Button(
           text='Calling msg in another class', 
           command=self.frames['StartPage'].pageone.msg) #<-- my mod 
self.frames['StartPage'].button3.pack() #<-- my mod 
+0

Приятно работать. Спасибо! Но трудно ли добавить ссылки между классами StartPage и PageOne? жаль, что это боль, но им любопытно, так как im new на python. В любом случае спасибо за помощь! –

+0

@MichaelCraig - Если у вас есть объект одного класса, который создает экземпляры другого, а для последнего нужны ссылки на первый, вы просто передаете ссылку (например, 'class A: def __init __ (self): b = B (self) '). Здесь, однако, вы создаете все те объекты на одном уровне, и один из них просто нуждается в ссылке на другую. Поскольку вы не можете ссылаться на вещи, которые еще не существуют, решение состоит в том, чтобы сначала создать все и добавить ссылку позже. – TigerhawkT3

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