I ran your script and didn't get any errors, but you made at least one mistake (arguably more).
- you delete the entry text, but then try to insert text at index 10
- you misspelled
otp1
(as 'opt1') in your loop
#generting otp
def generate(L=4):
entry.delete(0, END)
entry.insert(0, f'{random.choice(range(0, pow(10, L)))}'.zfill(L))
I believe this is much cleaner. The logic is dead simple. Generate a number from 0 to 9999 and pad the left side with zeroes for any number that has less than 4 characters. For longer or shorter numbers just change L
.
If you wanted to clean up your entire script. You may want to consider the following:
Unless you intend to do something with your Labels
, such as: change their text or remove them entirely, there is no reason to store a reference to them.
textvariable
expects a tk.StringVar()
, dumping an arbitrary str
into it does nothing (for me), but is probably the source of the error for you.
The user does not need to click a Button
to generate an arbitrary random number. You can simply generate it automatically as soon as the program executes.
Labels
with text like "USN" and "OTP" are not user-friendly.
import random
import tkinter as tk
root = tk.Tk()
root.title("OTP Generator ")
def random_key(L=4):
return f'{random.choice(range(0, pow(10, L)))}'.zfill(L)
#generate otp for this session
otp = random_key(8)
#GUI
tk.Label(root, text="Username:", anchor='e').grid(row=0, sticky='e')
usn_entry = tk.Entry(root)
usn_entry.grid(row=0 , column=1, sticky='w')
tk.Label(root, text="Phone Number:", anchor='e').grid(row=2, sticky='e')
phone_entry = tk.Entry(root)
phone_entry.grid(row=2, column=1, sticky='w')
tk.Label(root, text="PIN:", anchor='e').grid(row=4, sticky='e')
pin = tk.Entry(root, width=len(otp))
pin.grid(row=4, column=1, sticky='w')
pin.insert(0, otp)
pin.configure(state='read')
root.mainloop()
If you wanted to take it even further, you could consider that you keep creating the same Label
/Entry
combo, over and over. You could simply create a class
that represents that combination, and use it instead.
import random
import tkinter as tk
class LabeledEntry(tk.Frame):
@property
def text(self) -> str:
return self.__entry.get()
@text.setter
def text(self, value:str):
self.__entry.delete(0, 'end')
self.__entry.insert(0, value)
@property
def entry(self) -> tk.Entry:
return self.__entry
@property
def state(self) -> str:
return self.__entry['state']
@state.setter
def state(self, value:str):
self.__entry.configure(state=value)
def __init__(self, master, text:str, column=None, row=None, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.grid(column=column, row=row)
tk.Label(self, text=text, anchor='e', width=12).grid(row=0, column=0, sticky='e')
self.__entry = tk.Entry(self)
self.__entry.grid(row=0, column=1, sticky='w')
root = tk.Tk()
root.title("OTP Generator ")
def random_key(L=4):
return f'{random.choice(range(0, pow(10, L)))}'.zfill(L)
#generate otp for this session
otp = random_key(8)
#GUI
user_field = LabeledEntry(root, 'Username: ')
phone_field = LabeledEntry(root, 'Phone Number: ')
pin_field = LabeledEntry(root, 'PIN: ')
pin_field.text = otp
pin_field.state = 'read'
root.mainloop()