python - Llamando funciones de un Tkinter Frame a otro
function class (2)
Para llamar a un método en otro objeto, necesita una referencia al objeto. El código que copió para administrar las diferentes páginas está diseñado para facilitar esto, pero le falta una función para obtener la instancia de una página.
Entonces, lo primero que debe hacer es agregar un método
get_page
en el controlador:
class Myapp(tk.Tk):
...
def get_page(self, page_class):
return self.frames[page_class]
Con eso, puede obtener la instancia de la página, y con la instancia de la página puede llamar al método.
A continuación, debe mantener una referencia al controlador para poder llamarlo desde otras funciones:
class PageOne(tk.Frame):
def __init__(self, parent, controller):
self.controller = controller
...
Finalmente, ahora puede usar el controlador para obtener la página, y con la página puede llamar a la función.
Mi recomendación es no usar
lambda
menos que lo necesite absolutamente, y en este caso no lo necesita.
Es mucho más fácil escribir y depurar su código cuando utiliza las funciones adecuadas en lugar de
lambda
.
Por ejemplo:
class PageOne(tk.Frame):
def __init__(self, parent, controller):
...
button2 = ttk.Button(..., command=self.do_button)
...
def do_button(self):
page = self.controller.get_page(PageOne)
page.function()
Tengo una página donde mostraré algunos detalles de los clientes.
Así que creé una página llamada "detalles del cliente" con todas las etiquetas que necesito y configuré el texto de estas etiquetas como variables.
Lástima que no funcione.
Las etiquetas se crean en el método
__init__
, así que no puedo "actualizarlas", porque el init se llama solo al principio.
Entonces, lo que pensé es crear una nueva función que contenga todas las etiquetas y llamaré a esa función cuando tenga la necesidad ... aquí está el problema.
No puedo llamar a una función en otro
tk.Frame
.
El siguiente código es una versión simplificada del código.
import tkinter as tk
from tkinter import ttk
class Myapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = ttk.Frame(self, borderwidth=10, relief="sunken", width=200, height=100)
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 (HomePage, PageOne):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="N,S,E,W")
self.show_frame(HomePage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text="HomePage")
label.pack()
button1 = ttk.Button(self, text="Quit",
command=lambda: quit())
button1.pack()
button2 = ttk.Button(self, text="Call Function in the other page/class to show the label",
command=lambda: PageOne.function()) # this is to do it from an other class. I can''t do this
button2.pack()
button3 = ttk.Button(self, text="Page One",
command=lambda: controller.show_frame(PageOne))
button3.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text="PageOne")
label.pack()
button1 = ttk.Button(self, text="Quit",
command=lambda: quit())
button1.pack()
button2 = ttk.Button(self, text="Call Function, in local it works..",
command=lambda: self.function())#this is to do it in local
button2.pack()
button3 = ttk.Button(self, text="HomePage",
command=lambda: controller.show_frame(HomePage))
button3.pack()
def function(self):
label1 = ttk.Label(self, text="It Worked!")
label1.pack()
app = Myapp()
app.mainloop()
Podría considerar guardar referencias a los campos de la GUI que necesita actualizar, por ejemplo, en un dict en su clase MyApp. De esa manera, puede acceder a ellos desde cualquier lugar de la clase, independientemente de dónde se encuentre el elemento GUI real.
La programación GUI generalmente produce clases bastante desordenadas, el uso de un dict para realizar un seguimiento de los elementos reduce el desorden. A otros les gusta mantener atributos de clase separados para cada elemento al que necesite acceder más tarde.