0

Question:

I have 2 similar tkinter windows, which I would like to condense or modularise (because i have pretty much 2 of the exact same function), which would make the code more compact and more easily readable (whats the point of having 2 functions if i could have just one?).

How would i do this and should i use a class or a function?

Code:

from tkinter import * 
import sys

def register_normal():
    window1=Tk()
    window1.title('Registration')
    window1.geometry('300x300')

    def register(*args):
        print('This works aswell!')


    label_hidden=Label(window1, text="")
    photo1=PhotoImage(file='registration.png')
    photo_label1=Label(window1, image=photo1)
    label_hidden_1=Label(window1,text="")
    new_username_label=Label(window1,text='NEW USERNAME',font=('arial', 10, 'bold'))
    login_username=Entry(window1, width=40)
    label_hidden_2=Label(window1,text="")
    new_password_label=Label(window1,text='NEW MASTER PASSWORD',font=('arial', 10, 'bold'))
    login_password=Entry(window1,width=40, show='*')
    label_hidden_3=Label(window1,text="")

    login_btn=Button(window1,text='REGISTER',width=20,height=1,font=('arial', 10, 'bold'), command=register)
    login_password.bind('<Return>', register)

    label_hidden_1.pack()
    photo_label1.pack()
    label_hidden.pack()
    new_username_label.pack()
    login_username.pack()
    label_hidden_2.pack()
    new_password_label.pack()
    login_password.pack()
    label_hidden_3.pack()
    login_btn.pack()

    window1.mainloop()
    
def login_normal():
    window2=Tk()
    window2.title('Email Manager')
    window2.geometry('300x300')

    def login(*args):
        print('This works!')


    label_hidden=Label(window2, text="")
    photo2=PhotoImage(file='email.png')
    photo_label2=Label(window2, image=photo2)
    label_hidden_1=Label(window2,text="")
    username_lable=Label(window2,text='USERNAME',font=('arial', 10, 'bold'))
    login_username=Entry(window2, width=40)
    label_hidden_2=Label(window2,text="")
    password_lable=Label(window2,text='MASTER PASSWORD',font=('arial', 10, 'bold'))
    login_password=Entry(window2,width=40, show='*')
    label_hidden_3=Label(window2,text="")

    login_btn=Button(window2,text='LOGIN',width=20,height=1,font=('arial', 10, 'bold'), command=login)
    login_password.bind('<Return>', login)

    label_hidden_1.pack()
    photo_label2.pack()
    label_hidden.pack()
    username_lable.pack()
    login_username.pack()
    label_hidden_2.pack()
    password_lable.pack()
    login_password.pack()
    label_hidden_3.pack()
    login_btn.pack()

    window2.mainloop()


def main():
    register_normal()
    login_normal()
    
if __name__ == '__main__':
    main()

#===================================icons-and-pictures-author-attribute======================================#
#===========Icons made by "https://www.freepik.com" "Freepik" from "https://www.flaticon.com/" ==============#
#===================================icons-and-pictures-author-attribute======================================#
  • 1
    One is a register function and the other is a login function, both of them are not same, though if you feel you are repeating your self, create a class or a function even, then make these widgets and pass the variable datas as arguments, like text, callbacks, bla bla – Delrius Euphoria Jun 25 '21 at 00:00

1 Answers1

2

I will give you an example where you can use a template and then edit the values, I am using frames, which can be raised when pressed upon different button.

from tkinter import *

class Form(Frame):
    def __init__(self,master,user_txt,img,pw_txt,btn_txt,callback,*args,**kwargs):
        Frame.__init__(self,master,*args,**kwargs)
        
        self.photo1 = PhotoImage(file=img)
        Label(self, image=self.photo1).pack()
        Label(self,text=user_txt,font=('arial', 10, 'bold')).pack(pady=(50,0))
        
        self.e1 = Entry(self, width=40) # self because later needs to be accessed
        self.e1.pack(pady=(0,15))
       
        Label(self,text=pw_txt,font=('arial', 10, 'bold')).pack()
        
        self.e2 = Entry(self,width=40, show='*')
        self.e2.pack(pady=(0,15))

        login_btn = Button(self,text=btn_txt,width=20,height=1,font=('arial', 10, 'bold'), command=callback)
        self.e2.bind('<Return>', lambda e: callback())
        login_btn.pack(pady=(0,50))

def log(pg, e=None): # Do your password check and other stuff
    print('Username: ', pg.e1.get())
    print('Password: ', pg.e2.get())

def reg(pg, e=None):
    print('Reg Username: ', pg.e1.get())
    print('Reg Password: ', pg.e2.get())

if __name__ == '__main__':
    root = Tk()

    register = Form(root,'NEW USERNAME',None,'NEW MASTER PASSWORD','REGISTER',lambda: reg(register))
    login    = Form(root,'USERNAME',None,'MASTER PASSWORD','LOGIN',lambda: log(login))

    Button(root,text='Switch to register page',command=lambda: register.tkraise()).grid(row=1,column=0) # To raise register frame
    Button(root,text='Switch to login page',command=lambda: login.tkraise()).grid(row=2,column=0)

    register.grid(row=0,column=0) # Place in same place so can be raised with tkraise()
    login.grid(row=0,column=0)

    root.mainloop()

I have removed the blank labels and used pady=(up,down) to push the labels up and down. I have used classes instead of a function as it is instantiable. This example using frames will also get rid of creating more windows(more modern).

As you can see this is just a mere example because, a register form would need 2 password boxes(confirm password also), try to use this approach for similar concepts only, login and registration are different functions and hence their forms should also look different. You would just create a class called Login and then inherit from Frame and place it on the screen just like here, same with Registration. A good example of where to use this is a profile of a user, the template would be same for all users and only the user data would vary, which would be passed as variables.

For better understanding, read:

Delrius Euphoria
  • 14,910
  • 3
  • 15
  • 46