如何在Tkinter中连续运行窗口? (Python 2.7.11)

时间:2016-07-10 15:08:24

标签: python database login tkinter

我希望首先弹出一个登录窗口,然后一旦条件满足,关闭登录窗口,打开一个新窗口。

from Tkinter import *
import tkMessageBox

#Not really sure what i'm doing here anymore

while True:

    Login = Tk()
    Login.title('Login')
    Login.geometry('400x130')

    NameLabel = Label(Login, text='Username')
    NameLabel.place(bordermode=OUTSIDE, height=25, width=100, x=100)

    NameEntryRaw = Entry(Login)
    NameEntryRaw.place(bordermode=OUTSIDE, height=25, width=100, x=200)

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

    CodeEntryRaw = Entry(Login)
    CodeEntryRaw.place(bordermode=OUTSIDE, height=25, width=100, x=200, y=30)

    def tbd():

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

    def login():

        Usernames=list()
        Usernames.append('Mordecai')
        Usernames.append('Ezekiel')
        Usernames.append('Goliath')
        Usernames.append('Abraham')
        Usernames.append('Bartholomew')
        Usernames.append('Jedediah')
        Usernames.append('Solomon')
        Usernames.append('Tobias')
        Usernames.append('Yohanan')
        Usernames.append('Lucifer')

        NameEntry=NameEntryRaw.get()
        CodeEntry=CodeEntryRaw.get()

        CodeReal='116987'

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

        else:
            ()

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

        else:
            ()     

    LoginButton = Button(Login, text="Login", command=login)
    LoginButton.place(bordermode=OUTSIDE, height=50, width=200, x=100, y=60)
    Login.mainloop()

else:

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

2 个答案:

答案 0 :(得分:1)

您不想使用两个mainloop。一般来说,您的tkinter应用应该只有一个.mainloop来调用。

至于如何获取登录弹出窗口然后切换到窗口...您可以使用应用程序创建根窗口,当您启动程序时,会显示一个Toplevel窗口,其中包含登录内容,可能另外隐藏/撤销根?,让顶层有一个提交按钮或一些可以验证凭据的东西。如果凭据有效,那么您可以使用destroy()方法删除顶层窗口小部件/转到主应用程序的根窗口。

由于显而易见的原因,让while True重复创建GUI + mainloop的过程很糟糕。

编辑:静态可能是一个可变对象的坏词,因为它是可变的...为全局添加了元组与列表。

您不需要创建空白列表,然后使用append将您的用户名添加到usernames列表中。你可以使这个全球化。因为,用户名是一个可变对象(它是一个列表),你仍然可以在这个全局的代码中的其他地方执行操作,比如.append等。或者,如果你从来没有这些改变我会把它变成一个元组因为他们是不可改变的,这适合"意图更好。

不是使用.count(*)来获取列表中元素的出现,而是可以使用:

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

如果CodeReal是静态的,它看起来是静态的,你也可以将其设为全局。

这里是对代码的快速编辑,您可以在没有类的情况下执行此操作,但我在此处使用类来尝试清楚地显示程序中的逻辑分隔。

我也更改了一些变量名,因此更容易阅读/理解。我还使用了.pack().grid(),因为这比使用.place()所做的代码更快,这是一个随意的选择。

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?"):
        sys.exit()

#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.
        else:
            root.deiconify()
            app.pack()
            self.destroy()

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)
    Login()
    root.mainloop()

答案 1 :(得分:0)

我要感谢你澄清你为我做了什么。它被证明是非常有帮助的!这就是我与之建立的关系。我把这些名字放回原处,让它在没有课程的情况下工作,因为我觉得它有点难以使用。

from Tkinter import *
import tkMessageBox 
import sys
import binascii #Not for this part

Codenames = ['Mordecai', 'Ezekiel', 'Goliath', 'Abraham', 'Bartholomew',
    'Jedediah', 'Solomon', 'Tobias', 'Yohanan', 'Lucifer']

Password = '116987' 

def close_protocol():
    if tkMessageBox.askokcancel("Quit", "Do you want to quit?"):
        sys.exit()
#Below for a later part...
def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
    bits = bin(int(binascii.hexlify(text.encode(encoding, errors)), 16))[2:]
    return bits.zfill(8 * ((len(bits) + 7) // 8))

def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
    n = int(bits, 2)
    return int2bytes(n).decode(encoding, errors)

def int2bytes(i):
    hex_string = '%x' % i
    n = len(hex_string)
    return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
#Above for a later part...
SDB = Tk()
SDB.title("SMEGJALBYT DATA BASE")
SDB.withdraw()

SDBLogin = Toplevel()
SDBLogin.title("Login")

SDBLogin.wm_protocol("WM_DELETE_WINDOW", close_protocol)

CodenameLabel = Label(SDBLogin, text="Codename")
CodenameLabel.grid(row=0, column=0)

CodenameEntry = Entry(SDBLogin)
CodenameEntry.grid(row=0, column=2)

PasswordLabel = Label(SDBLogin, text="Password")
PasswordLabel.grid(row=1, column=0)

PasswordEntry = Entry(SDBLogin, show='*')
PasswordEntry.grid(row=1, column=2)

def login_operation():
    if CodenameEntry.get() not in Codenames:
        tkMessageBox.showinfo("INVALID CODENAME!", "Please verify input in the 'Codename' field")

    elif PasswordEntry.get() != Password:
        tkMessageBox.showinfo("INVALID PASSWORD!", "Please verify input in   the 'Password' field")

    else:
        SDB.deiconify()
        SDBLogin.destroy()

LoginButton = Button(SDBLogin, text="Login", command=login_operation)
LoginButton.grid(row=2, column=1)
#Code continues...
#Code finisles....
SDB.mainloop()

这具有相同的基本功能,只是按照我想要的方式组织。