Home > database >  How to open another window and close the current window in GUI?
How to open another window and close the current window in GUI?

Time:03-02

I'm new to Graphic User Interface using Python. I was able to open the register page after clicking the Register button from the login page.

Below is the code files:

login.py

from tkinter import *
from tkinter import ttk
from register import Register

class Login:
    def __init__(self):
        self.loginw = Tk()
        self.loginw.title("Login")
        self.loginw.geometry("500x500")
        
        self.signin = Button(self.loginw,width=20, text="Register", command=self.register)
        self.signin.place(relx=0.5, rely=0.5, anchor=CENTER)

    def register(self):
        win = Toplevel()
        Register(win)

w=Login()
w.loginw.mainloop()

register.py

from tkinter import *
from tkinter import ttk

class Register:
    def __init__(self, win):
        self.reg = win
        self.reg.title("Register")
        self.reg.geometry("500x500")
        
        self.revert = Button(self.reg,width=20, text="Return to Login")
        self.revert.place(relx=0.5, rely=0.5, anchor=CENTER)
        self.reg.mainloop()

Is there a way to write the code like:

  • After clicking the register button from the login page, the register page pops up and the login page disappears.
  • After clicking the Return to Login button from the register page, the register page disappears, and the login page comes back.

Thank you so much.

CodePudding user response:

Taken from another stackoverflow question:

import tkinter as tk                # python 3
from tkinter import font as tkfont  # python 3


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

In your case class StartPage could be your register page and PageOne your Login page. take that piece of code as a base to start.

Switch between two frames in tkinter

In this case the SampleApp class acts like the master frame (is a container) for other frames. So there is no pop up windows.

Another base template for tkinter app. Taken from the same link:

import tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self._frame = None
        self.switch_frame(Register)

    def switch_frame(self, frame_class):
        """Destroys current frame and replaces it with a new one."""
        new_frame = frame_class(self)
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self.geometry('925x600 ' self.screen() ' 20')
        self._frame.pack()

    def screen(self):
        screen_width = self.winfo_screenwidth()
        posX = (screen_width //2) - (925//2) 
        return str(posX)

class Register(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        tk.Label(self, text="This is the register Page").pack(side="top", fill="x", pady=10)
        tk.Button(self, text="Login",
                  command=lambda: master.switch_frame(Login)).pack()

class Login(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        tk.Label(self, text="Login Page").pack(side="top", fill="x", pady=10)
        self.usuario = tk.Entry(self)
        self.usuario.insert(-1, 'User')
        self.usuario.config(foreground='gray')
        self.usuario.pack(side="top", fill="x", padx=10, ipady=3)

        
        self.password = tk.Entry(self)
        self.password.insert(-1, "Password")
        self.password.config(foreground='gray')
        self.password.pack(side="top", fill="x", pady=10, padx=10, ipady=3)

        tk.Button(self, text="Return to register",
                  command=lambda: master.switch_frame(Register)).pack()
        tk.Button(self, text="Login",
                  command=lambda: print("not implemented yet")).pack()



if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

edit: to answer another question:

To change the title (in the first example) you must call inside one of these classes StartPage, PageOne, PageTwo

controller.title("the title you want")

That is because in this part of code (in the class SampleApp, the main class) you are passing itself as second parameter.

 self.frames = {}
    for F in (StartPage, PageOne, PageTwo):
        page_name = F.__name__
        frame = F(parent=container, controller=self) //controller=self
        self.frames[page_name] = frame

In the main class (SampleApp) you would do:

self.title("Some title")

In the second example:

master.title("Login")   //inside Login or Register
self.title("Something") //inside SampleApp
  • Related