Fonctions d'appel d'un cadre Tkinter vers un autre

j'ai une page où je montrerai quelques détails sur les clients. J'ai donc créé une page appelée "customers details" avec toutes les étiquettes dont j'ai besoin et j'ai défini le texte de ces étiquettes comme variables. Dommage qu'il ne fonctionne pas. Les étiquettes sont créées dans la méthode __init__ donc je ne peux pas les" mettre à jour", parce que l'init est appelé seulement au début. Donc, ce que j'ai pensé est de créer une nouvelle fonction qui contient toutes les étiquettes et je vais appeler cette fonction lorsque j'ai de la nécessité...voici l' problème. Je ne peux pas appeler une fonction dans un autre tk.Frame . Le code suivant est une version simplifiée du code.

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()
0
demandé sur martineau 2018-02-11 14:40:50

2 réponses

vous pouvez envisager de sauvegarder des références à vos champs GUI que vous devez mettre à jour, par exemple, un dict dans votre classe MyApp. De cette façon, vous pouvez accéder à eux de n'importe où dans la classe indépendamment de l'endroit où l'élément GUI réelle se trouve être placé.

GUI programmation produit généralement assez bordélique classes, à l'aide d'une dict à garder une trace des éléments qui réduit le désordre. D'autres aiment garder des attributs de classe séparés pour chaque élément que vous devez accéder plus tard.

0
répondu Patrik Iselind 2018-02-11 12:13:32

Pour appeler une méthode sur un autre objet, vous avez besoin d'une référence à l'objet. Le code que vous avez copié pour la gestion des différentes pages est conçu pour rendre cela facile, mais il manque une fonction pour obtenir l'instance d'une page.

donc, le premier que vous devez faire est d'ajouter une méthode get_page sur le contrôleur:

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

Avec cela, vous pouvez obtenir la page d'instance, et avec la page d'instance, vous pouvez appeler la méthode.

ensuite, vous devez conserver une référence au contrôleur pour pouvoir l'appeler à partir d'autres fonctions:

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

Enfin, vous pouvez maintenant utiliser le contrôleur pour obtenir la page, et la page, vous pouvez appeler la fonction.

ma recommandation est de ne pas utiliser lambda sauf si vous en avez absolument besoin, et dans ce cas vous ne le faites pas. Il est beaucoup plus facile d'écrire et de déboguer votre code lorsque vous utilisez des fonctions appropriées au lieu de lambda .

par exemple:

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()
0
répondu Bryan Oakley 2018-02-11 15:12:02