How to create a mandatory window in tkinter

I am using python 3.7 and tkinter for making a GUI which saves all my important passwords which are saved in a file passwords.txt. In this I want to create a button in my main window which pops up another window with an entry box and a button(which will close the window) and till this window is not closed it will not let the user to interact with my old window.

Here’s my codes:

from tkinter import *
from tkinter import ttk
root = Tk()
f = open("passwords.txt", "r")
list1 = []

for item in f.readlines():
    item = item.replace("n", "")
    list1.append(item)


def secondwindow():
    root2 = Tk()
    root2.title("Secure Your Password")
    root2.configure(bg="black")
    root2.geometry('700x600')
    frame_color = "#%02x%02x%02x" % (150,150,150)

    # Create A Main frame
    main_frame = Frame(root2, bg=frame_color)
    main_frame.pack(fill=BOTH,expand=1)

    # Create Frame for X Scrollbar
    sec = Frame(main_frame, bg=frame_color)
    sec.pack(fill=X,side=BOTTOM)

    # Create A Canvas
    my_canvas = Canvas(main_frame, bg="black")
    my_canvas.pack(side=LEFT,fill=BOTH,expand=1)

    # Add A Scrollbars to Canvas
    x_scrollbar = ttk.Scrollbar(sec,orient=HORIZONTAL,command=my_canvas.xview)
    x_scrollbar.pack(side=BOTTOM,fill=X)
    y_scrollbar = ttk.Scrollbar(main_frame,orient=VERTICAL,command=my_canvas.yview)
    y_scrollbar.pack(side=RIGHT,fill=Y)

    # Configure the canvas
    my_canvas.configure(xscrollcommand=x_scrollbar.set)
    my_canvas.configure(yscrollcommand=y_scrollbar.set)
    my_canvas.bind("<Configure>",lambda e: my_canvas.config(scrollregion= my_canvas.bbox(ALL))) 

    # Create Another Frame INSIDE the Canvas
    second_frame = Frame(my_canvas, bg=frame_color)

    # Add that New Frame a Window In The Canvas
    my_canvas.create_window((0,0),window=second_frame, anchor="nw")

    f = Frame(second_frame, borderwidth=2, relief=SUNKEN, bg=frame_color)
    f.pack(side=TOP, fill=X)
    Label(f, text="Secure Your Password", fg="white", bg=frame_color, font="Algerian 35 italic").pack()
    f1 = Frame(second_frame, bg="black")
    f1.pack(fill=BOTH, side=TOP, expand=1)
    Label(f1, text="Application", fg="red", bg="black", font="Calibri 20 bold", pady=10, padx=60).grid(row=1, column=1)
    Label(f1, text="Username", fg="red", bg="black", font="Calibri 20 bold", pady=10, padx=210).grid(row=1, column=2)
    Label(f1, text="Password", fg="red", bg="black", font="Calibri 20 bold", pady=10, padx=198).grid(row=1, column=3, padx=140)

    for i in range(len(list1)):
        application = list1[i].split(";;;")[0]
        username = list1[i].split(";;;")[1]
        password = list1[i].split(";;;")[2]
        Label(f1, text=application, fg="white", bg="black", font="Calibri 20 bold", pady=5).grid(row=i+2, column=1)
        Label(f1, text=username, fg="white", bg="black", font="Calibri 20 bold", pady=5).grid(row=i+2, column=2)
        Label(f1, text=password, fg="white", bg="black", font="Calibri 20 bold", pady=5).grid(row=i+2, column=3)

    root2.mainloop()


def checkPassword(password, l):
    if password == "a":
        root.destroy()
        secondwindow()

    else:
        l.config(text="Wrong Password")


def password_window():
    root.geometry('450x270')
    root.title("Secure Your Password")
    root.minsize(450, 270)
    root.maxsize(450, 270)
    root.configure(bg="black")

    Label(root, text="Secure Your Password", fg="white", bg="black", font="Algerian 24 italic").pack(side=TOP)
    Label(root, text="Your Password", fg="white", bg="black", font="Clibri 15").pack(pady=10)

    password = StringVar()
    Entry(root, textvariable=password, bg="grey", fg="white", font="Calibri 15 bold").pack(pady=10)
    Button(root, text="Login", bg="grey", fg="white", activebackground="grey", font="Calibri 10", command=lambda: checkPassword(password.get(), l)).pack(pady=8)

    l = Label(root, fg="red", bg="black", font="Clibri 10 bold")
    l.pack()


password_window()
root.mainloop()

And my passwords.txt:

StackOverflow;;;PomoGranade;;;PomoGranade_StackOverflow
GitHub;;;Pomogranade;;;PomoGranade_GitHub

I am new to python and tkinter. Thanks for help in advance 🙂

Answer

  1. I do not recommend using * imports, though it may not be exactly wrong in this case.

  2. Use the TopLevel widget instead of initialising another Tk window. See why using another Tk is not good.

Use .grab_set() (Look at @TheLizzard’s link in the comment for a better example)

Look at this example –

import tkinter as tk

root = tk.Tk()

def f1():
    top1 = tk.Toplevel(root)

    b2 = tk.Button(top1,text='Close New Window',command=top1.destroy)
    b2.pack()

    top1.grab_set()

b1 = tk.Button(root,text='Create Mandatory Window',command=f1)
b1.pack()


root.mainloop()

If you run this code, you will see that the first window does not react to any mouse press etc… and also you cannot close the first window after opening the new window until the it is closed