首页 > 解决方案 > 添加父窗口 Tkinter

问题描述

我已经使用 Tkinter 开发了一个 GUI 应用程序,但现在我想升级它并添加一个登录界面。我无法做到这一点我尝试制作登录表单,然后使用 TopLevel 方法但没有运气,很多标签、按钮、条目没有显示,我将附上整个代码。这是我的课

 class Student:
    def __init__(self,id,first,last,major):
        self.id=id
        self.first=first
        self.last=last
        self.major=major
        self.email=str(id)+'@students.liu.edu.lb'

    def allinfo(self):
        return 'ID={} , First_Name={} ,Last_Name={}, Major in {}, Email={}'.format(self.id,self.first,self.last,self.major,self.email)

    from tkinter import *
import tkinter as tk
def log():
    if(username_login_entry.get()=="admin" and password__login_entry.get()=="123"):
        print("access granted")
    
login_screen=Tk()
login_screen.title("Login")
login_screen.geometry("300x250")
Label(login_screen, text="Please enter login details").pack()
Label(login_screen, text="").pack()
Label(login_screen, text="Username").pack()
username_login_entry = Entry(login_screen, textvariable="username")
username_login_entry.pack()
Label(login_screen, text="").pack()
Label(login_screen, text="Password").pack()
password__login_entry = Entry(login_screen, textvariable="password", show= '*')
password__login_entry.pack()
Label(login_screen, text="").pack()
Button(login_screen,command=log, text="Login", width=10, height=1).pack()
login_screen.mainloop()

我想将登录添加到这个 GUI(附上它的图像),我希望代码在成功登录后转到这个应用程序

在此处输入图像描述

    from tkinter import *
import tkinter as tk
from student import *
from tkinter import messagebox
from tkinter import ttk
import tkinter.font as font
import pickle
import os
import cv2
num = 1 
path = 'images'                                  #Folder to store student's images
video = cv2.VideoCapture()                       #capture the video stream from the camera
frame = 0
tkWindow = tk.Tk()                               #Create a window ( UI )   
tkWindow.geometry('400x180')                     #Window Size   
tkWindow.title('Student Management System')      #Window Title

with open("studentlist.dat", "rb") as fp:        #Open the data file that store the student's list    
        SavedList = pickle.load(fp)
id = IntVar()                                    #Var to store data
id2=IntVar()                                     #Var to store data
fname = StringVar()                              #Var to store data
lname = StringVar()                              #Var to store data
major = StringVar()                              #Var to store data
idLabel = Label(tkWindow, text="Student ID : ").grid(row=0, column=0)
idEntry = Entry(tkWindow, textvariable=id).grid(row=0, column=1) 

fnameLabel = Label(tkWindow, text="Student FirstName : ").grid(row=1, column=0)
lnameEntry = Entry(tkWindow, textvariable=fname).grid(row=1, column=1) 

fnameLabel = Label(tkWindow, text="Student LastName : ").grid(row=3, column=0)
lnameEntry = Entry(tkWindow, textvariable=lname).grid(row=3, column=1)

majorLabel = Label(tkWindow, text="Student Major : ").grid(row=4, column=0)
majorEntry = Entry(tkWindow, textvariable=major).grid(row=4, column=1)
delLabel = Label(tkWindow, text="Delete a Student").grid(row=8, column=0)
delLabel = Label(tkWindow, text="ID of Student to Delete").grid(row=9, column=0)
delEntry = Entry(tkWindow, textvariable=id2).grid(row=9, column=1)


def RegStudent():                                  #Validation to Register a new student
    if len( fname.get()) >0 and len(lname.get() )> 0 and len(major.get()) > 0 and id.get() > 0 :

        try:
         SavedList.append(Student(id.get(),fname.get(),lname.get(),major.get()))   #add a student to the list
         with open("studentlist.dat", "wb") as fp:                                 #override the new list
                pickle.dump(SavedList, fp)
       
            
        except:
            print("Error")
def takePic():                                     #Method to take an image and save it to Path
   video = cv2.VideoCapture(0)
   a = 0
   while True:
        a = a + 1
        check, frame = video.read()
        cv2.imshow("Capturing",frame)
        key = cv2.waitKey(1)
        if key == ord('q'):
            SavePic = cv2.imwrite(os.path.join(path , fname.get()+' '+lname.get()+'.jpg'), frame)
            cv2.destroyAllWindows()
            break

cv2.destroyAllWindows()
video.release()


def listinfo():                                      # List the students along with their information
    if not SavedList:
        print("List is empty !")
        EmptyLabel = Label(tkWindow, text="List is empty").grid(row=5, column=2)
    for i in SavedList:
        print(i.allinfo()) 


def DeleteAllStudents():                               #Deletes all students                      
    for i in SavedList:
        SavedList.clear()
    with open("studentlist.dat", "wb") as fp:
        pickle.dump(SavedList, fp)
    return
            

def create_window():                                  #creates a window onclick
    window = tk.Toplevel(tkWindow)
    for i in range(len(SavedList)): 
            Label(window, text=SavedList[i].allinfo()).grid(row=i, column=0)
            
            
def del_std():                                       #deletes a specific student
    number=id2.get()
    for i in SavedList:
        if i.id==number:
            SavedList.remove(i)
            with open("studentlist.dat", "wb") as fp:
                pickle.dump(SavedList, fp)

    
                    
RegisterButton = Button(tkWindow, text="Add Student",command=RegStudent).grid(row=6, column=0)
listButton = Button(tkWindow, text="List Students",command=create_window).grid(row=6, column=1)
ClearButton = Button(tkWindow, text="Delete All Students ",command=DeleteAllStudents).grid(row=7, column=0)
TakePicButton = Button(tkWindow, text="Take picture ",command=takePic).grid(row=7, column=1)
delButton = Button(tkWindow, text="Delete ",command=del_std).grid(row=9, column=3)
tkWindow.mainloop()

标签: pythonuser-interfaceauthenticationtkinter

解决方案


我将您的所有代码放在一个文件中,它按预期工作 - 所以我不知道问题出在哪里。

但是因为同时我对这段代码进行了一些更改——为了使它更好地组织,具有可读的名称和新的功能——所以我把它放在这里。

我希望即使没有我的描述,它也会很有用。


#from tkinter import *  # PEP8: `import *` is not preferred
import os
import pickle
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import cv2
#from student import *


# --- classes ---

class Student():

    def __init__(self, id_number, first_name, last_name, major):
        self.id = id_number
        self.first_name = first_name
        self.last_name = last_name
        self.major = major

    def __str__(self):
        return '{} | {} {} | {}'.format(self.id, self.first_name, self.last_name, self.major)

    def allinfo(self):
        return str(self)  # `str()` will use code from `__str__`

# --- functions ---

def log(text, color='green'):
    #TODO: save it in log file

    # colors
    # https://misc.flogisoft.com/bash/tip_colors_and_formatting
    # or modules colorama, rich, etc.

    if color == 'green':
        print(f'\033[1;32m{text}\033[0m')
    elif color == 'red':
        print(f'\033[1;31m{text}\033[0m')
    elif color == 'yellow':
        print(f'\033[1;33m{text}\033[0m')
    elif color == 'blue':
        print(f'\033[1;34m{text}\033[0m')
    else:
        print('text')

    if messages_text is not None:
        messages_text.insert('end', text + "\n", color)


# ---

def login_window():
    #TODO: convert it to class (and maybe put in separated file)
    """Show login window"""

    def check():
        username = username_login_entry.get()
        password = password__login_entry.get()

        if username == "admin" and password =="123":
            print("access granted")
            log("[INFO] access granted", 'blue')
            login_screen.destroy()

    login_screen = tk.Tk()

    login_screen.title("Login")

    tk.Label(login_screen, text="Please enter login details").pack(pady=(20,0), padx=20)

    tk.Label(login_screen, text="Username").pack(pady=(20,0), padx=20)

    username_login_entry = tk.Entry(login_screen, textvariable="username", bg='white')
    username_login_entry.pack()

    tk.Label(login_screen, text="Password").pack(pady=(20,0), padx=20)

    password__login_entry = tk.Entry(login_screen, textvariable="password", show='*', bg='white')
    password__login_entry.pack()

    tk.Button(login_screen, text="Login", command=check, width=10).pack(pady=20, padx=20)

    login_screen.mainloop()

# ----

def read_data():
    log("[DEBUG] read_data(): read data from file", 'yellow')

    with open("studentlist.dat", "rb") as fp:
         data = pickle.load(fp)
    return data


def save_data(data):
    log("[DEBUG] save_data(): save data in file", 'yellow')

    with open("studentlist.dat", "wb") as fp:
         pickle.dump(data, fp)


def register_student():
    """Validation to Register a new student"""

    first_name = first_name_var.get()
    last_name  = last_name_var.get()
    major      = major_var.get()
    id_number  = id1_var.get()

    if first_name and last_name and major and id_number > 0:
    
        found = False
        
        for item in students:
            if item.id == id_number:
                found = True
                break
                
        if found:
            log("[ERROR] register_student(): ID already exists in database", 'red')
        else:
            try:
                item = Student(id_number, first_name, last_name, major)
                students.append(item)
                save_data(students)
            except Exception as ex:
                log("[ERROR] register_student(): " + str(ex), 'red')
    else:
        log("[ERROR] register_student(): wrong values", 'red')
    
    
def take_picture():
    """Take an image and save it to PATH"""

    video = cv2.VideoCapture(0)

    while True:
        check, frame = video.read()
        if check is True:
            cv2.imshow("Capturing", frame)
            key = cv2.waitKey(1)
            if key == ord('q'):
                filename = '{} {}.jpg'.format(first_name_var.get(), last_name_var.get())
                fullpath = os.path.join(PATH , filename)
                cv2.imwrite(fullpath, frame)
                break

    cv2.destroyAllWindows()
    video.release()


def list_students():
    """List the students along with their information"""

    if not students:
        print("List is empty !")
        # create label at start and here only change text
        messages_text.insert('end', "List is empty\n")

    for item in students:
        print(item.allinfo())


def delete_all_students():
    """Deletes all students"""

    students.clear()
    save_data(students)

    log("[INFO] delete_all_students(): Students deleted", 'blue')


def list_all_students():
    """Creates a window onclick"""

    window = tk.Toplevel(tkWindow)
    #for i in range(len(students)):
    #    tk.Label(window, text=students[i].allinfo()).grid(row=i, column=0)

    if not students:
        label = tk.Label(window, text="No students", bg='red')
        label.grid(row=0, column=0, ipadx=50, ipady=20, sticky='news')  # ipad = internal pad
        log("[INFO] list_all_student(): No students", 'blue')
    else:
        for i, item in enumerate(students):
            label = tk.Label(window, text=item.allinfo())
            label.grid(row=i, column=0)
        log("[INFO] list_all_student(): students " + str(len(students)), 'blue')


def delete_student():
    """Deletes a specific student"""
    id_number = id2_var.get()

    found = False

    for item in students:
        if item.id == id_number:
            students.remove(item)
            found = True
            break

    if found:
        save_data(students)
        log("[INFO] delete_student(): Student deleted", 'blue')
    else:
        log("[ERROR] delete_student(): Student not found", 'red')

# --- main ---

messages_text = None

login_window()

# - constants - (UPPER_CASE_NAMES)

PATH = 'images'  # Folder to store student's images

# - variables -

#num = 1

# - rest -

try:
    students = read_data()
except Exception as ex:
    log("[ERROR] start: " + str(ex), 'red')
    log("[DEBUG] start: create empty list of students", 'yellow')
    students = []

# - window -

tkWindow = tk.Tk()
#tkWindow.geometry('400x180')
tkWindow.title('Student Management System')

# - variables which has to be created after `tk.Tk()` -
id1_var = tk.IntVar()
id2_var = tk.IntVar()
first_name_var = tk.StringVar()
last_name_var = tk.StringVar()
major_var = tk.StringVar()

# - widgets -

# - widgets - add student -

frame_add = tk.LabelFrame(tkWindow, text="Add Student")
frame_add.pack(fill="both", expand=True, padx=10, pady=10)

frame_add.columnconfigure(1, weight=1)

label = tk.Label(frame_add, text="Student ID : ", anchor="e", width=20)
label.grid(row=0, column=0, sticky='we', pady=(0,5))

entry = tk.Entry(frame_add, textvariable=id1_var, bg='white')
entry.grid(row=0, column=1, sticky='we', columnspan=2, padx=(0,5), pady=(0,5))

label = tk.Label(frame_add, text="Student First Name : ", anchor="e", width=20)
label.grid(row=1, column=0, sticky='we', pady=(0,5))

entry = tk.Entry(frame_add, textvariable=first_name_var, bg='white')
entry.grid(row=1, column=1, sticky='we', columnspan=2, padx=(0,5), pady=(0,5))

label = tk.Label(frame_add, text="Student Last Name : ", anchor="e", width=20)
label.grid(row=3, column=0, sticky='we', pady=(0,5))

entry = tk.Entry(frame_add, textvariable=last_name_var, bg='white')
entry.grid(row=3, column=1, sticky='we', columnspan=2, padx=(0,5), pady=(0,5))

label = tk.Label(frame_add, text="Student Major : ", anchor="e", width=20)
label.grid(row=4, column=0, sticky='we', pady=(0,5))

entry = tk.Entry(frame_add, textvariable=major_var, bg='white')
entry.grid(row=4, column=1, sticky='we', columnspan=2, padx=(0,5), pady=(0,5))

button = tk.Button(frame_add, text="Take picture", command=take_picture, width=12)
button.grid(row=5, column=2, sticky='we', padx=(0,5), pady=(0,5))

button = tk.Button(frame_add, text="Add Student", command=register_student, width=12)
button.grid(row=6, column=2, sticky='we', padx=(0,5), pady=(0,5))


# - widgets - delete student -

frame_delete = tk.LabelFrame(tkWindow, text="Delete Student")
frame_delete.pack(fill="both", expand=True, padx=10, pady=10)

frame_delete.columnconfigure(1, weight=1)

label = tk.Label(frame_delete, text="Student ID : ", anchor="e", width=20)
label.grid(row=0, column=0, sticky='we', pady=(0,5))

entry = tk.Entry(frame_delete, textvariable=id2_var, bg='white')
entry.grid(row=0, column=1, sticky='we', columnspan=2, padx=(0,5), pady=(0,5))

button = tk.Button(frame_delete, text="Delete ", command=delete_student, width=12)
button.grid(row=1, column=2, sticky='we', padx=(0,5), pady=(0,5))

# - widgets - other -

frame_other = tk.LabelFrame(tkWindow, text="Other Functions")
frame_other.pack(fill="both", expand=True, padx=10, pady=10)

button = tk.Button(frame_other, text="List Students", command=list_all_students)
button.grid(row=0, column=0, sticky='we', padx=(5,0), pady=(5,5))

button = tk.Button(frame_other, text="Delete All Students", command=delete_all_students)
button.grid(row=0, column=1, sticky='we', padx=(5,5), pady=(5,5))

# - widgets - messages -

frame_message = tk.LabelFrame(tkWindow, text="Messages")
frame_message.pack(fill="both", expand=True, padx=10, pady=10)

messages_text = tk.Text(frame_message, height=10, bg='black')
messages_text.pack()
for color in ['red', 'green', 'yellow', 'blue']:
    messages_text.tag_config(color, foreground=color)

# - start -

tkWindow.mainloop()

Linux Mint 20 (MATE) 的屏幕截图

在此处输入图像描述


推荐阅读