I'm trying to build a random OTP generator but I coming across this error message, can anyone help me
error :
File "C:\Users\HP\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 2692, in insert
self.tk.call(self._w, 'insert', index, string)
_tkinter.TclError: wrong # args: should be ".!entry3 insert index text"
my code:
import random
from tkinter import *
from tkinter.ttk import *
root = Tk()
#generting otp
def generate():
entry.delete(0,END)
digits = "0123456789"
otp1 =""
for i in range (4):
opt1 = otp1 + random.choice (digits)
entry.insert(10,otp1)
#GUI
Usn_label = Label(root , text = "USN")
Usn_label.grid(row = 0 )
Usn_entry = Entry(root , textvariable='usn_var')
Usn_entry.grid(row =0 , column = 1)
phone_label = Label (root , text = " Phone Number ")
phone_label.grid (row = 2)
phone_entry = Entry (root , textvariable='phone number')
phone_entry.grid(row = 2, column = 1)
Gen_label =Button(root , text= 'Generate', command = generate)
Gen_label.grid (row = 3 , column = 1 , sticky='w')
Random_otp = Label (root, text = "OTP")
Random_otp.grid (row = 4 )
entry = Entry(root)
entry.grid(row = 4, column = 1)
root.title("Otp Generator ")
root.mainloop()
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()
Related
import random
import tkinter as tk
frame = tk.Tk()
frame.title("koeweils baldadige encyptor")
frame.geometry('400x200')
printButton = tk.Button(frame,text = "Print", command = lambda: zandkasteel())
printButton.pack()
freek = tk.Text(frame,height = 5, width = 20)
freek.pack()
input_a = freek.get(1.0, "end-1c")
print(input_a)
fruit = 0
fad = input_a[fruit:fruit+1]
print(fad)
schepje = len(input_a.strip("\n"))
print(schepje)
def zandkasteel():
lbl.config(text = "Ingevulde string: "+input_a)
with open("luchtballon.txt", "w") as chocoladeletter:
for i in range(schepje):
n = random.randint()
print(n)
leuk_woord = ord(fad)*n
print(leuk_woord)
chocoladeletter.write(str(leuk_woord))
chocoladeletter.write(str(n))
chocoladeletter.write('\n')
lbl = tk.Label(frame, text = "")
lbl.pack()
frame.mainloop()
I need to get the string that was entered into the text entry field freek. I have tried to assign that string to input_a, but the string doesn't show up.
Right now, input_a doesn't get anything assigned to it and seems to stay blank. I had the same function working before implementing a GUI, so the problem shouldn't lie with the def zandkasteel.
To be honest I really don't know what to try at this point, if you happen to have any insights, please do share and help out this newbie programmer in need.
Here are some simple modifications to your code that shows how to get the string in the Text widget when it's needed — specifically when the zandkasteel() function gets called in response to the user clicking on the Print button.
import random
import tkinter as tk
frame = tk.Tk()
frame.title("koeweils baldadige encyptor")
frame.geometry('400x200')
printButton = tk.Button(frame, text="Print", command=lambda: zandkasteel())
printButton.pack()
freek = tk.Text(frame, height=5, width=20)
freek.pack()
def zandkasteel():
input_a = freek.get(1.0, "end-1c")
print(f'{input_a=}')
fruit = 0
fad = input_a[fruit:fruit+1]
print(f'{fad=}')
schepje = len(input_a.strip("\n"))
print(f'{schepje=}')
lbl.config(text="Ingevulde string: " + input_a)
with open("luchtballon.txt", "w") as chocoladeletter:
for i in range(schepje):
n = random.randint(1, 3)
print(n)
leuk_woord = ord(fad)*n
print(leuk_woord)
chocoladeletter.write(str(leuk_woord))
chocoladeletter.write(str(n))
chocoladeletter.write('\n')
lbl = tk.Label(frame, text="")
lbl.pack()
frame.mainloop()
I have this issue where I need to display other function's values using the only button which is Calculate in this case. The first function is displayed but the other function not while using its text input field.
I've tried copying, using the same code expect changing the names.
import tkinter as tk
from functools import partial
n_num = list(map(int, input('Enter mean numbers: ').split()))
n = len(n_num)
get_sum = sum(n_num)
mean = get_sum / n
print("Mean / Average is: " + str(mean))
def mean_result (label_mean_result,num):
n_num = list(map(int,num.get()))
n = len(n_num)
get_sum = sum(n_num)
mean = get_sum /n
label_mean_result.config(text=f"Mean Result = {mean}")
return
def median_result (label_median_result,num):
n_num = list(map(int,num.get()))
n = len(n_num)
n_num.sort()
if n % 2 == 0:
median1 = n_num[n // 2]
median2 = n_num[n // 2 - 1]
median = (median1 + median2) / 2
else:
median = n_num[n // 2]
label_median_result.config(text=f"Median Result = {median}")
#print("Median is: " + str(median))
return
root = tk.Tk()
root.geometry('400x200+100+200')
root.title('Final program')
## Mean input and output
meanInput = tk.StringVar()
labelMean = tk.Label(root, text="Mean input:").grid(row=1, column=0)
labelResult = tk.Label(root)
labelResult.grid(row=7, column=2)
entryNum1 = tk.Entry(root, textvariable=meanInput).grid(row=1, column=2)
mean_result = partial(mean_result, labelResult, meanInput)
buttonCal = tk.Button(root, text="Calculate", command=mean_result).grid(row=3, column=0)
#####
medianInput = tk.StringVar()
labelMedian = tk.Label(root, text="Median input:").grid(row=2, column=0)
labelResult2 = tk.Label(root)
labelResult2.grid(row=7, column=2)
entryNum2 = tk.Entry(root, textvariable=medianInput).grid(row=2, column=2)
median_result= partial(median_result, labelResult2, medianInput)
root.mainloop()
I expect results when I input values from both functions using the only button in this case which is Calculate. As a result of that, I'd love to know how to connect multiple functions to one button and show their results. Like for example, the first function displays "mean function" result, however; the second function "median" is not connected and displayed while clicking at Calculate button.
import tkinter as tk
from statistics import median, mode, stdev
class Calculator(tk.Frame):
"""Calculate mean median mode and standard deviation"""
def __init__(self, parent, *args, **kwargs):
#setup tkinter frame
tk.Frame.__init__(self, parent, *args, **kwargs)
parent = parent
self.makeWidgets()
def makeWidgets(self):
"""make and pack various widgets"""
self.meanLabel = tk.Label(self, text="")
self.medianLabel = tk.Label(self, text="")
self.modeLabel = tk.Label(self, text="")
self.sdLabel = tk.Label(self, text="")
self.entry = tk.Entry(self)
self.calcuateButton = tk.Button(self, text="Calculate!", command = self.calculate)
self.meanLabel.pack()
self.medianLabel.pack()
self.modeLabel.pack()
self.sdLabel.pack()
self.entry.pack()
self.calcuateButton.pack()
def calculate(self):
self.listOfNumbers = self.entry.get()
#get what is inputed into the entry widget
self.listOfNumbers = self.listOfNumbers.split(' ')
#split the input string by spaces
for ind, i in enumerate(self.listOfNumbers):
#convert each item in the list of strings of numbers to ints
self.listOfNumbers[ind] = int(i)
#calculate!
self.calcMean()
self.calcMedian()
self.calcMode()
self.calcSd()
def calcMean(self):
"""calculate the mean"""
mean = sum(self.listOfNumbers)/len(self.listOfNumbers)
self.meanLabel.config(text='mean = ' + str(mean))
return mean
def calcMedian(self):
"""calculate the median"""
med = median(self.listOfNumbers)
self.medianLabel.config(text='median = ' + str(med))
return med
def calcMode(self):
"""calculate the mode"""
Mode = max(set(self.listOfNumbers), key=self.listOfNumbers.count)
self.modeLabel.config(text='mode = ' + str(Mode))
return Mode
def calcSd(self):
"""calculate the standard deviation"""
sd = stdev(self.listOfNumbers)
self.sdLabel.config(text='Standard deviation = ' + str(sd))
return sd
if __name__ == '__main__':
root = tk.Tk()
root.title('calculate mean, median, mode and standard deviation')
root.geometry('400x200')
Calculator(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Now this may be quite a bit different to what you had, but this is expandable and you can abstract things to suit your interest. I just find it much more readable
You calculated the median in your example, just thought it would be cleaner to use the statistics module. Mean is already pretty clean
I hope this helps :)
Edit; To include mode and sd;
from tkinter import ttk, simpledialog
import tkinter as tk
from tkinter import *
root = Tk()
root.resizable(0, 0)
root.title("Sorting and Searching Algorithm")
root.configure(bg='#ff8080')
root.geometry("750x550")
def arrays():
v = IntVar()
for widget in root.winfo_children():
widget.destroy()
def close():
for widget in root.winfo_children():
widget.destroy()
arrays()
titleFrame = Frame(root)
titleFrame.grid(row=0)
radioFrame = Frame(root)
radioFrame.grid(padx=350, pady=100)
inputFrame = tk.Frame(root, bg='#ff8080')
inputFrame.grid()
buttonFrame = Frame(root)
buttonFrame.grid()
Title = tk.Label(titleFrame, bg='#ff8080', text="Enter The Number of Elements In The Array", font="-weight bold")
Title.grid()
global NUMBER_OF_ENTRIES
NUMBER_OF_ENTRIES = Entry(inputFrame)
NUMBER_OF_ENTRIES.grid(row=0, column=1, sticky=E, ipadx=10, ipady=10,padx=10, pady=10)
if NUMBER_OF_ENTRIES == int:
print("Working")
else:
print("Please Enter a Integer Value")
global num
num = 0
#global NUMBER_OF_ENTRIES
#NUMBER_OF_ENTRIES = simpledialog.askinteger("Please Enter", "Enter The Number of Elements In The Array")
global alist
alist = []
for i in range (0, NUMBER_OF_ENTRIES):
num = simpledialog.askinteger("Please Enter" ,"Enter The Entries In Array Element " + str(i))
alist = alist + [ num ]
calculate = ttk.Button(buttonFrame, text="Proceed", command=entries)
calculate.grid(row=4, column=0, sticky=E + S, ipadx=10, ipady=10)
arrays()
root.mainloop()
I am trying to make it so when a user inputs a integer number into the Entry input box it stores into the variable NUMBER_OF_ENTRIES. After it stores it, it then proceeds to use the value in the further conditionals.
But I am getting an issue when I try to compile it.
Because it's not an integer. NUMBER_OF_ENTRIES is of type <class 'tkinter.Entry'>.
The usual way to do this is to associate the entry with a StringVar() which will reflect whatever is typed into the entry.
The text entered into an entry is still text so you'll have to convert it to int explicitly.
See The Tkinter Entry Widget.
I am trying to make a GUI where as soon as the user inputs an integer into a ttk.entry field, that many checkbuttons need to appear below it. For example, if they put "5" into the entry widget, 5 check buttons need to appear below the entry field.
Edit:
What I ended up using:
self.number_of_stages = tk.IntVar()
self.check_box_dict={}
self.num_of_stages={}
self.stagetempvar={}
self.equipment_widgets={}
def centrifugal_compressor_widgets(self):
self.equipment_widgets.clear()
self.equipment_widgets["NumOfStagesLabelCentComp"]=tk.Label(self.parent, text="Number of Stages:", bg="white")
self.equipment_widgets["NumOfStagesLabelCentComp"].place(relx=0.5, y=260, anchor="center")
self.equipment_widgets["NumOfStagesEntryCentComp"]=ttk.Entry(self.parent, textvariable=self.number_of_stages)
self.equipment_widgets["NumOfStagesEntryCentComp"].place(relx=0.5, y=290, anchor="center")
def OnTraceCentComp(self, varname, elementname, mode):
for key in self.check_box_dict:
self.check_box_dict[key].destroy()
try:
if self.number_of_stages.get() <=15 :
i=1
self.stagetempvar.clear()
while i <= self.number_of_stages.get():
self.stagetempvar[i]=tk.StringVar()
self.stagetempvar[i].set("Closed")
self.check_box_dict[i]=ttk.Checkbutton(self.parent, text=i, offvalue="Closed", onvalue="Open",variable=self.stagetempvar[i])
self.check_box_dict[i].place(relx=(i*(1/(self.number_of_stages.get()+1))), y=360, anchor="center")
i+=1
except:
pass
take a look at the below and let me know what you think...
A very ugly, super basic example:
from Tkinter import *
root = Tk()
root.geometry('200x200')
root.grid_rowconfigure(0, weight = 1)
root.grid_columnconfigure(0, weight = 1)
win1 = Frame(root, bg= 'blue')
win1.grid(row=0, column=0, sticky='news')
number = IntVar()
entry = Entry(win1, textvariable = number)
entry.pack()
confirm = Button(win1, text = 'Press to create widgets...', command = lambda:create_widgets(number.get()))
confirm.pack()
def create_widgets(number):
for n in range(0,number):
Checkbutton(win1, text = 'Checkbutton number : %s' % n).pack()
root.mainloop()
I'm trying to put old school sequential Tkinter code into class structure code.
So let's consider this example :
import Tkinter as Tk
def StartProcess():
print Text_1_Var.get(), Text_2_Var.get(), Text_3_Var.get()
if __name__ == '__main__':
MainFrame = Tk.Tk()
Tk.Button(MainFrame , text = "Start",command=StartProcess).grid(column=2, row=0)
Tk.Label(MainFrame , text = "1").grid(column=1, row=1)
Text_1_Var = Tk.StringVar()
Text_1 = Tk.Entry(MainFrame , width=40, textvariable = Text_1_Var).grid(column=2, row=1)
Tk.Label(MainFrame , text = "2").grid(column=1, row=2)
Text_2_Var = Tk.StringVar()
Text_2 = Tk.Entry(MainFrame , width=40, textvariable = Text_2_Var).grid(column=2, row=2)
Tk.Label(MainFrame , text = "3").grid(column=1, row=3)
Text_3_Var = Tk.StringVar()
Text_3 = Tk.Entry(MainFrame , width=40, textvariable = Text_3_Var).grid(column=2, row=3)
# etc
MainFrame.mainloop()
On press "Start" it displays values of Entry from 1 to 3.
Now i recode it as follow :
import Tkinter as Tk
def StartProcess():
print "???"
class NewEntry(Tk.Frame):
def __init__(self,master=None,idnumber=None):
Tk.Frame.__init__(self,master)
self.pack(side=Tk.TOP)
self.CreateWidgets(idnumber)
def CreateWidgets(self,idnumber):
Tk.Label(master=self, text = idnumber).grid(column=1, row=0)
self.Text_Var = Tk.StringVar()
self.Text = Tk.Entry(master=self, width=40, textvariable = self.Text_Var).grid(column=2, row=0)
if __name__ == '__main__':
MainFrame = Tk.Tk()
Tk.Button(master=MainFrame,text="Start", command=StartProcess).pack()
for i in range (1, 4): # or more
NewEntry(master=MainFrame,idnumber=str(i))
MainFrame.mainloop()
GUI are both identical. I want to get the same result but i don't know where my function StartProcess should take place and how extract value of each self.Text_Var instance.
It's not enough to create a NewEntry object; you need to save references to them so you can access them later (e.g., from StartProcess).
entries = []
for i in range (1, 4): # or more
e = NewEntry(master=MainFrame,idnumber=str(i))
entries.append(e)
# Or more simply,
# entries = [NewEntry(master=MainFrame, idnumber=str(i)) for i in range(1,4)]
Then, StartProcess becomes something like
def StartProcess():
strings = [x.Text_Var.get() for x in entries]
print " ".join(strings)