python - Chamar funções de um quadro Tkinter para outro




function class (2)

Eu tenho uma página onde mostrarei detalhes de alguns clientes. Por isso, criei uma página chamada "detalhes dos clientes" com todos os rótulos necessários e defino o texto desses rótulos como variáveis. Pena que não funciona. Os rótulos são criados no método __init__ , então não posso "atualizá-los", pois o init é chamado apenas no início. Então, o que pensei é criar uma nova função que contenha todos os rótulos e chamarei essa função quando tiver necessidade ... aqui está o problema. Não consigo chamar uma função em outro tk.Frame . O código a seguir é uma versão simplificada do 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()

Para chamar um método em outro objeto, você precisa de uma referência ao objeto. O código que você copiou para gerenciar as diferentes páginas foi projetado para facilitar isso, mas falta uma função para obter a instância de uma página.

Portanto, o primeiro que você precisa fazer é adicionar um método get_page no controlador:

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

Com isso, você pode obter a instância da página e, com a instância da página, pode chamar o método

Em seguida, você precisa manter uma referência ao controlador para poder chamá-lo de outras funções:

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

Finalmente, agora você pode usar o controlador para obter a página e, com a página, pode chamar a função.

Minha recomendação é não usar lambda menos que você precise absolutamente e, nesse caso, não. É muito mais fácil escrever e depurar seu código quando você usa funções apropriadas em vez de lambda .

Por exemplo:

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

Você pode considerar salvar referências nos campos da GUI que precisa atualizar, por exemplo, um ditado na sua classe MyApp. Dessa forma, você pode acessá-los de qualquer lugar da classe, independentemente de onde o elemento GUI real é colocado.

A programação da GUI geralmente produz classes bastante confusas, usando um comando para acompanhar os elementos reduz a confusão. Outros gostam de manter atributos de classe separados para cada elemento que você precisa acessar mais tarde.