如何访问tkinter python中不同类的variables3

我一直在寻找很多,我仍然不知道如何从python的不同类访问variables…在这种情况下,我想访问variablesself.vPageOne类到PageTwo类..请帮助我

这是我的代码…

 import tkinter as tk import smtplib TITLE_FONT = ("Helvetica", 18, "bold") class SampleApp(tk.Tk): def __init__(self): tk.Tk.__init__(self) 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): frame = F(container, self) self.frames[F] = frame frame.grid(row=0, column=0, sticky="nsew") self.show_frame(StartPage) def show_frame(self, c): frame = self.frames[c] frame.tkraise() class StartPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) label = tk.Label(self, text="PyMail",foreground = "Red", font=("Courier", 30, "bold")) label.pack(side="top") sublabel = tk.Label(self, text="Bringing you the\n the easiest way of communication", font=("Courier", 15)) sublabel.pack() wallpaper = tk.PhotoImage(file='Python-logo-notext.gif') img = tk.Label(self, image=wallpaper) img.image = wallpaper img.pack(side="top", expand = True) button1 = tk.Button(self, text="Click Here to Login to your account",fg="red", command=lambda: controller.show_frame(PageOne)) button2 = tk.Button(self, text="Go to Page Two", command=lambda: controller.show_frame(PageTwo)) button2.pack(side="bottom") button1.pack(side="bottom") class PageOne(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller=controller label = tk.Label(self, text="Personal Information", font=TITLE_FONT, foreground="blue") label.pack(side="top", fill="x", pady=10) global optionv self.optionv = tk.StringVar() self.optionv.set("---Select One---") optionm = tk.OptionMenu(self, self.optionv, "---Select One---", "@gmail.com", "@yahoo.com", "@hotmail.com") t1 = tk.Label(self, text="Email Account: ") self.v = tk.StringVar() self.v.set("") entry1 = tk.Entry(self, textvariable=self.v) t2 = tk.Label(self,text="\nPassword: ") self.pwd = tk.StringVar() self.pwd.set("") entry2 = tk.Entry(self, textvariable=self.pwd) entry2.config(show="*") lgbutton=tk.Button(self, text="Log In", command=self.login) button = tk.Button(self, text="Go to the start page", command=lambda: controller.show_frame(StartPage)) #final = tk.Label(self, textvariable=self.v) #finalpwd = tk.Label(self, textvariable=self.pwd) t1.pack() entry1.pack() optionm.pack() t2.pack() entry2.pack() #final.pack() #finalpwd.pack() lgbutton.pack() button.pack(side="bottom") def login(self): value = tk.Label(self, text="Invalid username / password", font=("Courier", 15, "bold"), foreground="red") success = tk.Label(self, text="Login was Successful \n (Click ""Continue"" to compose email)", font=("Courier", 15, "bold"), foreground="blue") cbutton = tk.Button(self, text="Continue", command=lambda: self.controller.show_frame(PageTwo)) status = tk.Label(self, text="Please select your email domain", foreground="red") if self.optionv.get() == "@gmail.com": try: global server server = smtplib.SMTP("smtp.gmail.com", 587) server.ehlo() server.starttls() server.login(self.v.get()+self.optionv.get(), self.pwd.get()) success.pack() cbutton.pack(side="bottom") except: value.pack() elif self.optionv.get() == "@yahoo.com": try: server = smtplib.SMTP("smtp.yahoo.com", 587) server.ehlo() server.starttls() server.login(self.v.get()+self.optionv.get(), self.pwd.get()) success.pack() cbutton.pack(side="bottom") except: value.pack() elif self.optionv.get() == "@hotmail.com": try: server = smtplib.SMTP("smtp.live.com", 587) server.ehlo() server.starttls() server.login(self.v.get()+self.optionv.get(), self.pwd.get()) success.pack() cbutton.pack(side="bottom") except: value.pack() else: status.pack() class PageTwo(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) label = tk.Label(self, text="Compose Mail", font=TITLE_FONT, foreground="green") label.pack(side="top", fill="x", pady=10) self.reciever = tk.StringVar() self.reciever.set("") senderl = tk.Label(self, text="Send to: ") rmail = tk.Entry(self, textvariable=self.reciever) self.senderoption = tk.StringVar() self.senderoption.set("---Select One---") senderdomain = tk.OptionMenu(self, self.senderoption, "---Select One---", "@gmail.com", "@hotmail.com", "@yahoo.com") self.mail = tk.StringVar() self.mail.set("") self.textw = tk.Entry(self, textvariable=self.mail) button = tk.Button(self, text="Go to the start page", command=lambda: controller.show_frame(StartPage)) sendbutton = tk.Button(self, text = "Send Mail", command=self.sendmail) senderl.pack(side="top", anchor="w") rmail.pack(side="top", anchor="nw") senderdomain.pack(side="top", anchor="nw") self.textw.pack(fill="both") button.pack(side="bottom") sendbutton.pack(side="bottom") def sendmail(self): sent = tk.Label(self, text="Email has been sent") if self.senderoption.get() == "@gmail.com": try: server.sendmail(self.v.get()+self.optionv.get(), self.reciever.get()+self.senderoption.get(), "YES") print("Success") sent.pack() except: print("Unsuccesful") print(PageOne.self.v.get()) if __name__ == "__main__": app = SampleApp() app.title("PyMail") app.geometry("400x400") app.mainloop() 

在其核心,你的问题有一个简单的答案。 “如何从对象X获得价值? 任何对象的答案都是一样的:通过询问对象X来得到它。为了做到这一点,所有你需要的就是获得对象的引用,然后直接访问属性。

从其他页面访问数据

在你的情况下, PageTwo的代码需要对PageOne的引用,所以你可以得到vvariables。

那么,你如何得到一个参考? 代码(您从教程中复制的,或者从教程复制而来的stackoverflow答案 )被devise为使得这一点变得简单。 每个页面都有一个对控制器的引用,并且这个控制器有一个对每个页面的引用。 因此你可以要求pipe理员给你一个页面的引用。

第一步是在每个类中保存对控制器的引用。 有趣的是,您已经在PageOne执行此操作,但是您应该在所有页面中执行此操作。 确保在每个__init__方法中添加self.controller = controller ,如下所示:

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

接下来,我们需要在控制器类中添加一个方法,该方法将返回对页面的引用。 将以下函数添加到SampleApp

 class SampleApp(tk.Tk): ... def get_page(self, page_class): return self.frames[page_class] ... 

现在,从任何“页面”中,您都可以访问任何其他“页面”的对象。 例如,在PageTwo您可以像这样访问PageOnevvariables:

 page1 = self.controller.get_page(PageOne) page1.v.set("Hello, world") 

使用共享数据

一个更好的解决scheme是让您的SampleApp类创build一组所有页面共享的variables。 您可以在该类中创build一个字典,然后使用控制器为每个页面提供访问权限。 例如:

 class SampleApp(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) self.shared_data = { "username": tk.StringVar(), "password": tk.StringVar(), ... ) 

那么,从任何一个class级你都可以像这样访问数据:

 entry1 = tk.Entry(self, textvariable=self.controller.shared_data["username"]) ... username = self.controller.shared_data["username"].get() 

这是更好的解决scheme的原因是您的网页不必知道其他网页是如何实现的。 当一个页面依赖于另一个页面的确切实现时,这被称为紧密耦合 。 如果页面不需要知道其他页面是如何实现的,则称为松耦合

松耦合给你更多的灵活性。 不是每个页面都紧密耦合到每一个页面,而是与一个对象紧密耦合:控制器。 只要每个页面只知道控制器,每个页面随时都可以自由更改,而不影响程序的其余部分。

当然,如果更换控制器,则必须更改所有的页面,但是如果您devise的控制器不太可能发生并且在发生时更容易pipe理,那么该控制器的devise就很好。

这与全球框架有关。

如果您在类中创build一个variables,它将只存在于该函数内部。 如果你想在一个类(或者函数,就此而言)中把一个variables“传递”到全局框架中,你可以使用全局的

 class firstClass(): global my_var_first my_var_first = "first variable" print(my_var_first) # This will work, because the var is in the global frame class secondClass(): my_var_second = "second variable" print(my_var_first) # This will work, as the var is in the global frame and not defined in the class print(my_var_second) # This won't work, because there is no my_var_second in the global frame 

为了可视化内存,可以使用pythontutor ,因为它会一步一步向您显示如何创build内存。

我希望我能帮助你!

编辑

我想我应该补充一点,如果你在全局框架中定义了一个名字与variables相同的variables,它将不会删除全局variables。 相反,它将在其自己的框架中创build一个新的(具有相同的名称)。 如果可用,类或函数将始终在其自己的框架中使用该variables。

 x = 5 def print_variable(): x = 3 print(x) print(x) print_variable() # OUTPUT: # 5 # 3