Home > Mobile >  Can't switch over to another window in Tkinter
Can't switch over to another window in Tkinter

Time:12-15

I've reorganised my question.

I have a two windows(in two different .py files) in one project built on Tkinter:

  1. Login/Security UI which takes login and password. There is a "Login" button linked to the class' method which checks the name/pass pair and returns True if login data is correct
  2. Main app UI.

So the problem is : after entering the correct username and password and pressing the button "Login" (this part works just fine, becouse i'm getting into correct IF section and method returns True) which supposed to call a Main UI window i got nothing happened. After closing manualy the Login window the second Tk() object (UI window) appears.

My code of Login UI:

class Security:
    def __init__(self):
        # -------- Window arrangement ------------------- #
        self.root = Tk()
        self.root.title("Gym Activity Tracker")
        self.root.minsize(600, 300)
        self.user_name = StringVar()
        self.user_pass = StringVar()

        # --------- Login labels ---------- #
        self.user_label = Label(text="User: ")
        self.user_label.grid(column=0, row=1, pady=(20, 5))
        self.password_label = Label(text="Password: ", padx=50)
        self.password_label.grid(column=0, row=2, pady=(0, 10))
        self.info_label = Label(text="(Optional)", anchor="e")
        self.info_label.grid(column=2, row=2)

        # --------- Login Buttons ---------- #
        self.login_button = Button(text="Login", width=25, command=self.security_check)
        self.login_button.grid(column=1, row=3)

        # --------- Login Entries ---------- #
        self.user_name_var = StringVar(self.root)
        self.user_name_var.set("Choose an User")
        self.user_drop_list = OptionMenu(self.root, self.user_name_var, "sdf")
        self.user_drop_list.config(width=24)
        self.user_drop_list.grid(column=1, row=1, pady=(20, 5))
        self.password_entry = Entry(width=30)
        self.password_entry.grid(column=1, row=2)

        self.root.mainloop()

    def security_check(self):

        """Method validates the user's name and password (if applied) entered
        and returns True if security check has been passed"""
        user_name_entered = self.user_name_var.get()
        user_password_entered = self.password_entry.get()

        data = pd.read_csv("settings/users_list.csv")
        database_user_pass = data.loc[data.name == f"{user_name_entered}", "password"]
        if (f"{user_name_entered}" in data["name"].values) and (str(database_user_pass[1]) == user_password_entered):
            return True and self.root.destroy()

        elif f"{user_name_entered}" not in data["name"].values:
            tkinter.messagebox.showwarning(
                title="Username error",
                message="User does not exist. Please check a spelling or create a new user"
            )
            return False

        elif str(database_user_pass) == user_password_entered:
            tkinter.messagebox.showwarning(
                title="Password error",
                message="Password is not correct for this user"
            )
            return False

        else:
            print("Something went wrong with Security Check")
            return False

Which runs from main.py :

from frames.security import Security
from frames.ui import MainInterface


def main():
    authorization = Security()
    if authorization.security_check():
        app = MainInterface()

Functionality of Security/Login window works well. Functionality of Main UI windows works well too.

How to make a programm to close the Security/Login window and run another Toplevel window? After executing the self.root.destroy() command in security_check function i get the tkinter error can't invoke "destroy" command: application has been destroyed

CodePudding user response:

I'm not exactly sure on how to fix your issue but instead you could try to use ''' sys.exit(1) ''' after you exit out of the UI

CodePudding user response:

It is not recommended to call mainloop() inside __init__(). Create another class method for this.

Also you should return the login status from the above-mentioned class method and don't call security_check() again as it is already called when Login button is clicked. You should destroy the login window inside security_check() when the login is successful.

frames/security.py

from tkinter import *
import tkinter.messagebox
import pandas as pd

class Security:
    def __init__(self):
        # -------- Window arrangement ------------------- #
        self.root = Tk()
        self.root.title("Gym Activity Tracker")
        self.root.minsize(600, 300)
        # instance variable for login status
        self.login_passed = False
        self.user_name = StringVar()
        self.user_pass = StringVar()

        # --------- Login labels ---------- #
        self.user_label = Label(text="User: ")
        self.user_label.grid(column=0, row=1, pady=(20, 5))
        self.password_label = Label(text="Password: ", padx=50)
        self.password_label.grid(column=0, row=2, pady=(0, 10))
        self.info_label = Label(text="(Optional)", anchor="e")
        self.info_label.grid(column=2, row=2)

        # --------- Login Buttons ---------- #
        self.login_button = Button(text="Login", width=25, command=self.security_check)
        self.login_button.grid(column=1, row=3)

        # --------- Login Entries ---------- #
        self.user_name_var = StringVar(self.root)
        self.user_name_var.set("Choose an User")
        self.user_drop_list = OptionMenu(self.root, self.user_name_var, "sdf")
        self.user_drop_list.config(width=24)
        self.user_drop_list.grid(column=1, row=1, pady=(20, 5))
        self.password_entry = Entry(width=30)
        self.password_entry.grid(column=1, row=2)

        # don't call mainloop() inside __init__()

    def run(self):
        self.root.mainloop()
        return self.login_passed

    def security_check(self):

        """Method validates the user's name and password (if applied) entered
        and returns True if security check has been passed"""
        user_name_entered = self.user_name_var.get()
        user_password_entered = self.password_entry.get()

        data = pd.read_csv("settings/users_list.csv")
        database_user_pass = data.loc[data.name == f"{user_name_entered}", "password"]
        if (f"{user_name_entered}" in data["name"].values) and (str(database_user_pass[0]) == user_password_entered):
            # set login status to successful
            self.login_passed = True
            # destroy the login window
            self.root.destroy()
            return True

        elif f"{user_name_entered}" not in data["name"].values:
            tkinter.messagebox.showwarning(
                title="Username error",
                message="User does not exist. Please check a spelling or create a new user"
            )
            return False

        elif str(database_user_pass) != user_password_entered:  ####
            tkinter.messagebox.showwarning(
                title="Password error",
                message="Password is not correct for this user"
            )
            return False

        else:
            print("Something went wrong with Security Check")
            return False
main.py
from frames.security import Security
from frames.ui import MainInterface


def main():
    authorization = Security().run()
    if authorization:
        app = MainInterface()
  • Related