Eine Möglichkeit besteht darin, die Frames übereinander zu stapeln. Anschließend können Sie sie einfach in der Stapelreihenfolge übereinander heben. Der obere wird derjenige sein, der sichtbar ist. Dies funktioniert am besten, wenn alle Frames die gleiche Größe haben, aber mit ein wenig Arbeit können Sie es mit Frames beliebiger Größe zum Laufen bringen.
Hinweis : Damit dies funktioniert, müssen alle Widgets für eine Seite diese Seite (dh :) self
oder einen Nachkommen als übergeordnetes Element (oder Master, je nach der von Ihnen bevorzugten Terminologie) haben.
Hier ist ein Beispiel, das Ihnen das allgemeine Konzept zeigt:
try:
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
except ImportError:
import Tkinter as tk # python 2
import tkFont as tkfont # python 2
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
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):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Go to Page One",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Go to Page Two",
command=lambda: controller.show_frame("PageTwo"))
button1.pack()
button2.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 2", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
Wenn Sie das Konzept des Erstellens einer Instanz in einer Klasse verwirrend finden oder wenn verschiedene Seiten während der Erstellung unterschiedliche Argumente benötigen, können Sie jede Klasse explizit separat aufrufen. Die Schleife dient hauptsächlich dazu, den Punkt zu veranschaulichen, dass jede Klasse identisch ist.
Um beispielsweise die Klassen einzeln zu erstellen, können Sie die Schleife entfernen ( for F in (StartPage, ...)
damit:
self.frames["StartPage"] = StartPage(parent=container, controller=self)
self.frames["PageOne"] = PageOne(parent=container, controller=self)
self.frames["PageTwo"] = PageTwo(parent=container, controller=self)
self.frames["StartPage"].grid(row=0, column=0, sticky="nsew")
self.frames["PageOne"].grid(row=0, column=0, sticky="nsew")
self.frames["PageTwo"].grid(row=0, column=0, sticky="nsew")
Im Laufe der Zeit haben Leute andere Fragen gestellt, wobei sie diesen Code (oder ein Online-Tutorial, das diesen Code kopiert hat) als Ausgangspunkt verwendet haben. Vielleicht möchten Sie die Antworten auf diese Fragen lesen:
pack_forget
kann verwendet werden, wenn Sie verwendenpack
.Hier ist eine weitere einfache Antwort, jedoch ohne Verwendung von Klassen.
quelle
Eine Möglichkeit, Frames einzuschalten,
tkinter
besteht darin, den alten Frame zu zerstören und ihn dann durch Ihren neuen Frame zu ersetzen.Ich habe Bryan Oakleys Antwort geändert , um den alten Rahmen zu zerstören, bevor ich ihn ersetzte. Als zusätzlichen Bonus wird ein
container
Objekt überflüssig und Sie können jede generischeFrame
Klasse verwenden.Erläuterung
switch_frame()
Akzeptiert jedes implementierte KlassenobjektFrame
. Die Funktion erstellt dann einen neuen Rahmen, um den alten zu ersetzen._frame
falls vorhanden, und ersetzt sie durch den neuen Frame..pack()
, wie z. B. Menüleisten, bleiben davon unberührt.tkinter.Frame
.Versionsgeschichte
quelle
self
) direkt an die Rahmenklasse anhängen .switch_frame()
könnte der Name etwas irreführend sein. Soll ich es umbenennenreplace_frame()
?