para instalar examples descargar python user-interface python-3.x tkinter smtplib

python - instalar - ¿Cómo acceder a variables de diferentes clases en tkinter?



tkinter examples (2)

He estado buscando mucho y todavía no sé cómo acceder a variables de diferentes clases en Python. En este caso, quiero acceder a la variable self.v de la clase PageTwo clase PageTwo .

Aquí está mi código.

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


En esencia, su pregunta tiene una respuesta simple. "¿Cómo obtengo un valor del objeto X?" La respuesta es la misma para cualquier objeto: lo obtienes preguntando al objeto X. Todo lo que necesitas para hacer eso es obtener una referencia al objeto y luego acceder al atributo directamente.

Acceso a datos desde otras páginas

En su caso, el código en PageTwo necesita una referencia a PageOne para que pueda obtener la variable v .

Entonces, ¿cómo se obtiene una referencia? El código (que copió de un tutorial o de la respuesta de de la que copió el tutorial) fue diseñado para facilitar esto. Cada página recibe una referencia a un controlador, y este controlador tiene una referencia a cada página. Por lo tanto, puede pedirle al controlador que le dé una referencia a una página.

El primer paso es guardar la referencia al controlador en cada clase. Curiosamente, ya está haciendo esto en PageOne , pero debe hacerlo en todas las páginas. Asegúrese de agregar self.controller = controller en cada método __init__ , así:

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

A continuación, debemos agregar un método en la clase de controlador que devolverá una referencia a la página. Agregue la siguiente función a SampleApp :

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

Ahora, desde cualquier "página" puede obtener acceso al objeto para cualquier otra "página". Por ejemplo, en PageTwo puede acceder a la variable v desde PageOne esta manera:

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

Usar datos compartidos

Una solución aún mejor es que su clase SampleApp cree un conjunto único de variables que compartan todas las páginas. Puede crear un diccionario en esa clase y luego usar el controlador para dar acceso a cada página. Por ejemplo:

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

Luego, desde cualquier clase, puede acceder a los datos de esta manera:

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

La razón por la que es la mejor solución es que sus páginas no tienen que saber cómo se implementan las otras páginas. Cuando una página se basa en la implementación exacta de otra página, esto se denomina acoplamiento estrecho . Si las páginas no necesitan saber cómo se implementan las otras páginas, esto se llama acoplamiento flojo .

El acoplamiento suelto le brinda más flexibilidad. En lugar de tener cada página estrechamente acoplada a cada otra página, todas están estrechamente acopladas a un solo objeto: el controlador. Siempre que cada página sepa solo sobre el controlador, cada página puede modificarse en cualquier momento sin afectar el resto del programa.

Por supuesto, si cambia el controlador, debe cambiar todas las páginas, pero si hace un buen trabajo diseñando el controlador, es menos probable que ocurra y sea más fácil de administrar cuando ocurra.


Esto tiene que ver con el marco global.

Si crea una variable dentro de una clase, solo existirá dentro de esa función. Si desea ''transferir'' una variable dentro de una clase (o función, para el caso) al marco global, utilice global .

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

Para visualizar la memoria, puede usar pythontutor , ya que le mostrará paso a paso cómo se crea la memoria.

¡Espero que te pueda ayudar!

EDITAR

Creo que debería agregar que si define una variable dentro de una clase / función con el mismo nombre que una variable en el marco global, no eliminará la variable global. En su lugar, creará uno nuevo (con el mismo nombre) en su propio marco. Una clase o función siempre usará la variable en su propio marco si está disponible.

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