friedmanism friedmanism - 3 months ago 5x
Python Question

How can I make windows in Tkinter that run in succession? (Python 2.7.11)

I want to have a login window pop up at first, then once the conditions are satisfied, it closes the login window and opens a new window.

from Tkinter import *
import tkMessageBox

#Not really sure what i'm doing here anymore

while True:

Login = Tk()

NameLabel = Label(Login, text='Username'), height=25, width=100, x=100)

NameEntryRaw = Entry(Login), height=25, width=100, x=200)

CodeLabel = Label(Login, text='Code'), height=25, width=100, x=100, y=30)

CodeEntryRaw = Entry(Login), height=25, width=100, x=200, y=30)

def tbd():

tkMessageBox.showinfo('Congrats!', 'This program is not done yet')

def login():




if Usernames.count(NameEntry) == 0:
tkMessageBox.showinfo('Error!', 'Your Username is invalid! Try Again.')


if CodeEntry != CodeReal:
tkMessageBox.showinfo('Error!', 'The Code entered is invalid! Try Again.')


LoginButton = Button(Login, text="Login", command=login), height=50, width=200, x=100, y=60)


DataBase = Tk()
#this will be the data base


You don't want to use two mainloop's. Generally speaking, your tkinter app should have a single .mainloop called.

As for how to get the login popup and then switch to the window... You can create your root window with the app and when you start your program have a Toplevel window be shown with the login stuff, maybe hide / withdraw the root additionally?, have the toplevel have a submit button or something that would validate the credentials. If the credentials are valid, then you can use the destroy() method and remove the toplevel widget / go to the root window for your main app.

Having a while True repeat the process of creating a GUI + mainloop is bad for obvious reasons.

Edit: static is probably a bad term for a mutable object, since it's mutable... Added tuple vs list for global.

You don't need to create a blank list and then use append to add your usernames to the usernames list. You can make this global. Since, username is a mutable object (it's a list) you could still perform operations elsewhere in your code on this global, say .append etc. Or, if you never have these change i'd make it a tuple, since they're immutable and this "fits" better with the intent.

Instead of using .count(*) to get the occurrences of an element in a list you can just use:

if (object) in (some list) #Object is an abstraction, not the type

If CodeReal is static, which it looks to be, you can also make this global.

Here's a quick edit to your code, you can do this without classes, but I used classes here to try to distinctly show the logical separation in the program.

I changed a few variable names as well, so that it was easier to read / understand. I also used .pack() and .grid() as this was quicker to code than having to use .place() everywhere this is an arbitrary choice.

import Tkinter as tk 
import tkMessageBox as messagebox
import sys

#No need to do usernames = list() and then .append for each one.
#Just make a global list holding them all...
USERNAMES = ('Mordecai', 'Ezekiel', 'Goliath', 'Abraham', 'Bartholomew',
    'Jedediah', 'Solomon', 'Tobias', 'Yohanan', 'Lucifer')
PASSWORD = '116987' #Was CodeReal, this can be global

#We overrode the closing protocol here.
def closing_protocol():

    if messagebox.askokcancel("Quit", "Do you want to quit?"):

#A container for our Login "app".
class Login(tk.Toplevel):

    def __init__(self, *args, **kwargs):

        #We init the toplevel widget.
        tk.Toplevel.__init__(self, *args, **kwargs)

        #We set the closing protocol to be the overridden version / func.
        self.wm_protocol("WM_DELETE_WINDOW", closing_protocol)
        tk.Label(self, text='Username').grid(row=0, column=0)
        self.username = tk.Entry(self)
        self.username.grid(row=0, column=1)

        tk.Label(self, text='Password').grid(row=1, column=0)
        #Show = '*' just hides the password instead of plain-text like
        #you typically see
        self.password = tk.Entry(self, text='Password', show='*')
        self.password.grid(row=1, column=1)

        #When the button is clicked the _callback function will be called
        tk.Button(self, text='Login', command=self._callback).\
            grid(row=2, column=0, columnspan=2, sticky="nsew")

    def _callback(self):

        #If the username or password is bad, raise an error message.
        if (self.username.get() not in USERNAMES or 
            self.password.get() != PASSWORD):
            messagebox.showerror("Validation Error!", 
                "You have entered invalid credentials.\n" +
                "Please try again.")

        #otherwise, we're good to go. Destroy login / show main app.

class Main(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)
        tk.Label(self, text="MAIN APP STUFF").pack()

if __name__ == '__main__':

    root = tk.Tk()
    root.withdraw() #Hides the root window initially.
    app = Main(root)