In this tutorial, we will take a look at how to make a login UI. Today's tutorial will focus on how to use the Tkinter's pack
layout manager.
Designing The UI
What is a layout manager? When you create graphical interfaces, the widgets in the window must have a way to be arranged relative to each other. For example, placing widgets can be accomplished using their relative positions to other widgets or by defining their positions by specifying pixel locations. In Tkinter there are three types of layout managers -- pack
, place
, and grid
. Each manager uses a different method to help us arrange widgets. To find out more about the differences between the three methods, please check out this tutorial.
Layout of login UI created in this tutorial using Tkinter.
Login UIs are everywhere, on your phone, computer, at the bank, and more. It is essential to gather a user's information and check if the input matches data which is already in the system.
Take a look at the image of the login UI above. We'll need to create a label to display the text "Login". Then, add the user's personal image. Next are the fields where they can enter their username, password, and check a box if they want the computer to remember their information for the next time. Since it is beyond the scope of this tutorial, the "Forgot password" link is simply a placeholder.
Pack Layout Manager
So what is pack
? The simplest way to think about it is that the pack()
method turns each individual widget into a block. Each widget has its own size and the pack
manager fits them all together just like you would do with real blocks.
Each widget already has its own size and parameters. Of course, you can change these to better fit your needs. Once every widget's size is determined, the manager does its job to arrange them in the window.
Create GUI Applications with Python & Qt6 by Martin Fitzpatrick — (PyQt6 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!
Let's take a moment to learn some of the basics of the pack
layout manager. With pack
, the manager stacks widgets on top of each other vertically like blocks. Of course, you can also achieve a horizontal layout by changing the side
parameter to 'left'
or 'right'
. You can also change the height, width, and locations of the widgets. Some of the pack
manager's more useful parameters are listed below:
side
-- specifies the general location of the widget in the window, arguments are'top'
,'bottom'
,'left'
,'right'
(default is'top'
).fill
-- which directions you want the widget to fill in the parent window, can choose'x'
,'y'
directions, or'both'
.padx
,pady
-- the number of pixels surrounding the widget to create a padding between other widgets, for horizontal or vertical padding.ipadx
,ipady
-- how many pixels to use for padding inside the widget, also for horizontal or vertical paddingexpand
-- set toTrue
if you want the widget to stretch if the parent window expands. Default isFalse
.anchor
-- where the widget is placed in the parent widget, specified by'n'
,'s'
,'e'
,'w'
, or some combination of them. Default is'center'
.
Create A Simple UI With Pack
The geometry manager pack
is very useful for general case GUIs. Below is a simple example of how to create a UI and arrange widgets in the window with pack()
.
from tkinter import *
root = Tk()
root.title("Using Pack")
root.geometry("300x100") # set starting size of window
root.config(bg="skyblue")
# Example of how to arrange Button widget using pack
button1 = Button(root, text="Click me")
button1.pack(side="left")
# Example of how to arrange Label widgets using pack
label1 = Label(root, text="Read me", bg="skyblue")
label1.pack(side="right")
label2 = Label(root, text="Hello", bg="purple")
label2.pack(side="right")
def toggled():
'''display a message to the terminal every time the check button
is clicked'''
print("The check button works.")
# Example of how to arrange Checkbutton widget using pack
var = IntVar() # Variable to check if checkbox is clicked, or not
check = Checkbutton(root, text="Click me", bg="skyblue", command=toggled, variable=var)
check.pack(side="bottom")
root.mainloop()
First, let's import the Tkinter module and create the main root
window in lines 1-6.
Example of how pack can arrange widgets.
In lines 9-10, we create the first Button
widget. Notice how the widget is arranged on the left of the window using the side="left"
argument in line 10. Next, let's see what happens if we want to place widgets on the right (lines 14-17). Here we arrange two labels in the window using side="right"
. Notice how label2
is placed to the right of label1
. In order to place label2
under label1
you would need to create a Frame
widget to contain them. Keep in mind that if you use pack
with a complex GUI your code can get more complex as well. An example of this can be seen below with the login UI.
Finally, let's look at the Checkbutton
on the bottom. Pack automatically centers widgets in their respective areas. Changing the anchor
value to 'w'
can help to move the checkbox to the left a little bit.
Creating The Login UI
Now let's get to the login UI! The following is the entire code for the GUI.
from tkinter import *
root = Tk()
root.title("Login UI using Pack")
root.geometry("400x320") # set starting size of window
root.maxsize(400, 320) # width x height
root.config(bg="#6FAFE7") # set background color of root window
login = Label(root, text="Login", bg="#2176C1", fg='white', relief=RAISED)
login.pack(ipady=5, fill='x')
login.config(font=("Font", 30)) # change font and size of label
# login image
image = PhotoImage(file="redhuli_favicon.gif")
img_resize = image.subsample(5,5)
Label(root, image=img_resize, bg="white", relief=SUNKEN).pack(pady=5)
def checkInput():
'''check that the username and password match'''
usernm = "Username301"
pswrd = "Passw0rd"
entered_usernm = username_entry.get() # get username from Entry widget
entered_pswrd = password_entry.get() # get password from Entry widget
if (usernm == entered_usernm) and (pswrd == entered_pswrd):
print("Hello!")
root.destroy()
else:
print("Login failed: Invalid username or password.")
def toggled():
'''display a message to the terminal every time the check button
is clicked'''
print("The check button works.")
# Username Entry
username_frame = Frame(root, bg="#6FAFE7")
username_frame.pack()
Label(username_frame, text="Username", bg="#6FAFE7").pack(side='left', padx=5)
username_entry = Entry(username_frame, bd=3)
username_entry.pack(side='right')
# Password entry
password_frame = Frame(root, bg="#6FAFE7")
password_frame.pack()
Label(password_frame, text="Password", bg="#6FAFE7").pack(side='left', padx=7)
password_entry = Entry(password_frame, bd=3)
password_entry.pack(side='right')
# Create Go! Button
go_button = Button(root, text="GO!", command=checkInput, bg="#6FAFE7", width=15)
go_button.pack(pady=5)
# Remember me and forgot password
bottom_frame = Frame(root, bg="#6FAFE7")
bottom_frame.pack()
var = IntVar()
remember_me = Checkbutton(bottom_frame, text="Remember me", bg="#6FAFE7", command=toggled, variable=var)
remember_me.pack(side='left', padx=19)
# The forgot password Label is just a placeholder, has no function currently
forgot_pswrd = Label(bottom_frame, text="Forgot password?", bg="#6FAFE7")
forgot_pswrd.pack(side="right", padx=19)
root.mainloop()
The pack
layout manager works best for simple layouts. The login UI consists mostly of a few vertical widgets stacked on top of each other. So this is a perfect opportunity to experiment with pack()
.
Begin by setting up the root window, its size and background color. Then the first two widgets, the login
Label
and user image
, are created and placed in the root
window. These two are the easiest since they are simply two widgets arranged vertically.
For the username, password, and "Remember me" areas, these are a little more complex. Because they are each sets of two different widgets each arranged horizontally, AND because we already have the login
and image
widgets arranged vertically, we need to create a Frame
widget for each one. These frames will also be stacked under the widgets we already created. Each Frame
will hold two widgets.
Let's take a look at the first one. In line 38, we create the username_frame
object that will contain both the "username" text and the Entry
widget for usernames to type in their name. You'll create these in lines 43-44. Notice how the side arguments are 'left'
and 'right'
to arrange them horizontally in username_frame
. The other two areas we create in a similar fashion. I won't include their description here since it is similar.
After the user types in their information and clicks the "GO!" button, we call checkInput()
(lines 18 -- 30) to check if the information entered by the user matches what is already stored in our program on lines 20 and 21. If they match, then the window closes by calling root.destroy()
.
Login UI created using Tkinter and Python.
Summary
In this tutorial, we looked at how to use the pack method by creating two separate UIs. We also look at the how to arrange widgets in both simple and slightly more complex layouts.
Of course there are still tons of ways to improve the look and functionality of this GUI. For one thing, you could actually allow the user to create their own username and password, and write that information to an output file. Another thing you could do is allow the UI to store the user's information using the "Remember me" Checkbutton
. Also, you could change the "Forgot password" Label
into a link that redirects the user to a new window. Furthermore, you could let the user select their own image for their profile by searching for a local file on their computer.