In this Python Tkinter tutorial, I will show you how to create and manage multiple windows in a GUI application. I will use the Toplevel widget to open new windows from the main window. By the end of this tutorial, you’ll be able to handle multiple windows in your Tkinter apps with ease.
Let’s begin.
Python Tkinter Multiple Windows
We are learning about how multiple windows work. By Multiple Windows, we mean connecting one page with other pages that are interlinked with each other and open in a new tab or even redirect us to a new page.
Code:
import tkinter as tk
def New_Window():
Window = tk.Toplevel()
canvas = tk.Canvas(Window, height=HEIGHT, width=WIDTH)
canvas.pack()
HEIGHT = 300
WIDTH = 500
ws = tk.Tk()
ws.title("Python Guides")
canvas = tk.Canvas(ws, height=HEIGHT, width=WIDTH)
canvas.pack()
button = tk.Button(ws, text="Click ME", bg='White', fg='Black',
command=lambda: New_Window())
button.pack()
ws.mainloop()Here are some of the main highlights of the given code.
- ws is used for the root window
- HEIGHT = height of the canvas widget.
- WIDTH = width is used for the canvas widget.
- bg is used for background color.
- fg is used for the foreground color.
- tk.Button() is used to add buttons.
Output:

As we can see a button in the above output, and clicking on the “Click Me” button opens a new window. And the result is shown below.

Read Create a Date Time Picker using Python Tkinter
Python Tkinter User Registration using Multiple Windows
We have to make a Registration form in which we made columns of blocks carrying information related to name, email, and password. It also verifies email using OTP to check the genuine user for a healthy database.
Code:
Some libraries that we are using in this code are:
- sqllite3.connect() is used for database connectivity
- Label() is used to display text in this user just view, not interact.
- Entry() is a single-line textbox to accept a value from the user.
from tkinter import *
import re
from tkinter import messagebox
import sqlite3
import random
from email.message import EmailMessage
import smtplib
# Database
try:
con = sqlite3.connect('website.db')
con.execute('''create table if not exists users(
fname text not null,
lname text not null,
email text not null,
password text not null);
''')
con.close()
except Exception as ep:
messagebox.showerror('', ep)
ws = Tk()
ws.title('Python Guides')
ws.geometry('500x400')
ws.config(bg="#447c84")
ws.attributes('-fullscreen',True)
# functions
def otp_gen():
pass
cpy = ''
def sendOtp():
otp_no = ''
for _ in range(4)
r = random.randint(0, 9)
otp_no += str(r)
global cpy
cpy += otp_no
sender = "[email protected]"
reciever = em.get()
password = "Cute...pie@0823"
msg_body = f'otp is {cpy}'
msg = EmailMessage()
msg['subject'] = 'OTP'
msg['from'] = sender
msg['to'] = reciever
msg.set_content(msg_body)
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(sender,password)
smtp.send_message(msg)
print(cpy)
return cpy
def clr():
fname.delete(0, END)
lname.delete(0, END)
em.delete(0, END)
pwd.delete(0, END)
def submit():
enteredOtp = otp.get()
expectedOtp = cpy
print(expectedOtp)
fname_check = fname.get()
lname_check = lname.get()
em_check = em.get()
pwd_check = pwd.get()
otp_check = otp.get()
check_count = 0
if fname_check == "":
warn = "First name can't be empty!"
else:
check_count += 1
if lname_check == "":
warn = "Last name can't be empty!"
else:
check_count += 1
if em_check == "":
warn = "Email can't be empty!"
else:
check_count += 1
if pwd_check == "":
warn = "Password can't be empty!"
else:
check_count += 1
if otp_check == "":
warn = "Otp can't be empty!"
else:
check_count += 1
# if fname_check, lname_check, pwd_check, otp_check:
if check_count == 5:
if (expectedOtp == enteredOtp):
con = sqlite3.connect('website.db')
c = con.cursor()
c.execute("insert into users VALUES (:fname, :lname, :em, :pwd)",{
'fname': fname.get(),
'lname': lname.get(),
'em': em.get(),
'pwd': pwd.get()
})
con.commit()
ws.destroy()
import app
else:
messagebox.showerror('','Incorrect Otp')
else:
messagebox.showerror('', warn)
# frames
frame = Frame(ws, padx=20, pady=20)
frame.pack(expand=True)
# labels
Label(
frame,
text="Create New Account",
font=("Times", "24", "bold")
).grid(row=0, columnspan=3, pady=10)
Label(
frame,
text='First Name',
font=("Times", "14")
).grid(row=1, column=0, pady=5)
Label(
frame,
text='Last Name',
font=("Times", "14")
).grid(row=2, column=0, pady=5)
Label(
frame,
text='Email Address',
font=("Times", "14")
).grid(row=3, column=0, pady=5)
Label(
frame,
text='Password',
font=("Times", "14")
).grid(row=4, column=0, pady=5)
Label(
frame,
text='Enter OTP',
font=("Times", "14")
).grid(row=5, column=0, pady=5)
# Entry
fname = Entry(frame, width=30)
lname = Entry(frame, width=30)
em = Entry(frame, width=30)
pwd = Entry(frame, width=30)
otp = Entry(frame, width=30)
fname.grid(row=1, column=1)
lname.grid(row=2, column=1)
em.grid(row=3, column=1)
pwd.grid(row=4, column=1)
otp.grid(row=5, column=1)
# button
clr = Button(frame, text="Clear", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=clr)
reg = Button(frame, text="Register", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=submit)
ext = Button(frame, text="Exit", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=lambda:ws.destroy())
otpp = Button(frame, text="verify email", padx=10, relief=RAISED, font=("Times", "10", "bold"), command=sendOtp)
clr.grid(row=6, column=0, pady=20)
reg.grid(row=6, column=1, pady=20)
ext.grid(row=6, column=2, pady=20)
otpp.grid(row=5, column=2)
ws.mainloop(Output:
In the above code, we made a registration form that carries details like labels, buttons, and entries are used in this code, which is connected with a database connection that adds a genuine user to register here.

In the below output, we fill in all the details and verify the email to proceed further.

As we check and enter an OTP randomly, as we can see, there is an error showing with the message “Incorrect OTP”. It means we can not move further until we provide the correct OTP and email address that we used while registering.

Check out Implement Drag and Drop Functionality in Python Tkinter
Python Tkinter Multi-page access verification
By access verification, we mean to verify a user’s password and email that are registered during registration. We can also register a user using a create account button inside this code.
Login Page.py
Now, let’s have a look at some libraries that we use in this code:
- un is used for username
- pd is used for Password
- messagebox.showerror() is used when an incorrect username and password are entered; it automatically shows an error.
from tkinter import *
from tkinter import messagebox
import sqlite3
try:
con = sqlite3.connect('website.db')
c = con.cursor()
c.execute("Select * from users")
for i in c.fetchall():
un = i[2]
pd = i[3]
except Exception as ep:
messagebox.showerror('', ep)
ws = Tk()
ws.title('Python Guides')
ws.geometry('500x400')
ws.config(bg="#447c84")
ws.attributes('-fullscreen',True)
def createAccount():
ws.destroy()
import register
def submit():
u = uname.get()
p = pwd.get()
check_counter=0
if u == "":
warn = "Username can't be empty"
else:
check_counter += 1
if p == "":
warn = "Password can't be empty"
else:
check_counter += 1
if check_counter == 2:
if (u == un and p == pd):
ws.destroy()
import app
else:
messagebox.showerror('', 'invalid username or password')
else:
messagebox.showerror('', warn)
# frame
frame = Frame(ws, padx=20, pady=20)
frame.pack_propagate(False)
frame.pack(expand=True)
# labels
Label(
frame,
text="Admin Login",
font=("Times", "24", "bold")
).grid(row=0, columnspan=3, pady=10) #..place(x=170, y=10)
Label(
frame,
text='Enter Username',
font=("Times", "14")
).grid(row=1, column=1, pady=5) #.place(x=50, y=70)
Label(
frame,
text='Enter Password',
font=("Times", "14")
).grid(row=2, column=1, pady=5) #.place(x=50, y=110)
# Entry
uname = Entry(frame, width=20)
pwd = Entry(frame, width=20, show="*")
# uname.place(x=220, y=70)
# pwd.place(x=220, y=110)
uname.grid(row=1, column=2)
pwd.grid(row=2, column=2)
# button
reg = Button(
frame,
text="Create Account",
padx=20, pady=10,
relief=RAISED,
font=("Times", "14", "bold"),
command=createAccount
)
sub = Button(
frame,
text="Login",
padx=20,
pady=10,
relief=RAISED,
font=("Times", "14", "bold"),
command=submit
)
reg.grid(row=3, column=1, pady=10)
sub.grid(row=3, column=2, pady=10)
ws.mainloop()Output:
After running the above code, we got this output, in which we can see labels of “enter username“, “enter password“, and two buttons working on different functionality.

In the below output, we enter an email inside a username and password under the password section and click on the “Login” button.

As we can see, a username and password were entered wrong by a user and which shows it does not redirect us to another window or a page.

App.py
Here is some more code that is working to run another page once the verification process is done.
from tkinter import *
from tkinter import messagebox
ws = Tk()
ws.title('Python Guides')
ws.geometry('500x300')
ws.config(bg="#447c84")
ws.attributes('-fullscreen',True)
# functions
def msg():
return messagebox.showinfo('', 'Life is short, \n do what you love')
def logOut():
resp = messagebox.askquestion('', 'Are you sure?')
if resp == 'yes':
ws.destroy()
else:
pass
# frames
frame = Frame(
ws,
padx=20,
pady=20
)
frame.pack(expand=True)
# image
img = PhotoImage(file='img.png')
# labelslo
Label(
frame,
text="Congratulations!",
font=("Times", "24", "bold")
).grid(row=0, columnspan=3)
Label(
frame,
text='Your Account is Active',
fg='green',
font=("Times", "14")
).grid(row=1, columnspan=3)
imglbl = Label(frame, image=img)
imglbl.grid(row=2, column=1)
# button
exp = Button(frame, text="open>>", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=msg)
logout = Button(frame, text="Logout", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=logOut)
exp.grid(row=2 , column=1)
logout.grid(row=3, column=1)
ws.mainloop()After running the following code and clicking on the Login button, we have to enter a valid username and password. And it will redirect us to another window and show us the following message.
Also, we can see a logout button that will help us exit the page.

In this tutorial, I explained Python Tkinter multiple windows with its examples and also covered Python Tkinter multiple windows, Python Tkinter user registration using multiple windows, and Python Tkinter Multi-page access verification.
You may also like to read the following Tkinter tutorials:
- Read a Text File and Display the Contents in a Tkinter With Python
- Upload a File in Python Tkinter
- Navigate Between Pages in a Python Tkinter

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.