python - Aufrufen von Funktionen von einem Tkinter-Frame zu einem anderen




function class (2)

Sie können Verweise auf Ihre GUI-Felder speichern, die Sie beispielsweise in einem Diktat in Ihrer MyApp-Klasse aktualisieren müssen. Auf diese Weise können Sie von überall in der Klasse darauf zugreifen, unabhängig davon, wo sich das eigentliche GUI-Element befindet.

Die GUI-Programmierung erzeugt normalerweise ziemlich unübersichtliche Klassen. Die Verwendung eines Diktats, um die Elemente im Auge zu behalten, reduziert die Unübersichtlichkeit. Andere möchten separate Klassenattribute für jedes Element behalten, auf das Sie später zugreifen müssen.

Ich habe eine Seite, auf der ich einige Kundendaten anzeigen werde. Deshalb habe ich eine Seite namens "Kundendetails" mit allen benötigten Beschriftungen erstellt und den Text dieser Beschriftungen als Variablen festgelegt. Schade, dass es nicht funktioniert. Die Labels werden in der __init__ Methode erstellt, sodass ich sie nicht "aktualisieren" kann, da der init-Befehl nur am Anfang aufgerufen wird. Also, was ich dachte, ist eine neue Funktion zu erstellen, die alle Labels enthält und ich werde diese Funktion aufrufen, wenn ich die Notwendigkeit habe ... hier ist das Problem. Ich kann eine Funktion in einem anderen tk.Frame nicht tk.Frame . Der folgende Code ist eine vereinfachte Version des Codes.

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

Um eine Methode für ein anderes Objekt aufzurufen, benötigen Sie einen Verweis auf das Objekt. Der Code, den Sie zum Verwalten der verschiedenen Seiten kopiert haben, soll dies vereinfachen. Es fehlt jedoch eine Funktion zum Abrufen der Instanz einer Seite.

Der erste get_page , den Sie tun müssen, ist das Hinzufügen einer get_page Methode auf dem Controller:

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

Damit erhalten Sie die Seiteninstanz und mit der Seiteninstanz können Sie die Methode aufrufen.

Als Nächstes müssen Sie einen Verweis auf den Controller behalten, damit Sie ihn von anderen Funktionen aus aufrufen können:

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

Schließlich können Sie jetzt den Controller verwenden, um die Seite abzurufen, und mit der Seite können Sie die Funktion aufrufen.

Ich empfehle, lambda wenn Sie es unbedingt benötigen, und in diesem Fall nicht. Es ist viel einfacher, Code zu schreiben und zu debuggen, wenn Sie anstelle von lambda die richtigen Funktionen verwenden.

Zum Beispiel:

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






frame