Stack Overflow Asked by rickifernando on January 29, 2021
I have a problem in my code ,
I was using python and tkinter to develop my programs,
but i have a problem that make me stuck for a while ,
i was build an Employee Attandance application,
An employee have an ID ,
so in my application Employee input his/her id on textboxt in my form
like this
enter image description here
the problem is ,each employee has len(id) between 9 and 10
so i think i create an event triggered start after len(id) input is 9
ids = StringVar(value="")
ids.trace("w", lambda name, index, mode, ids=ids: textchanged(ids))
inputid = tkinter.Entry(window,font="Helvetica 20 bold",textvariable=ids)
inputid.pack()
inputid.place(relx=0.5,rely=0.187,width=300,height=30,anchor='sw',)
inputid.size()
def textchanged(ids):
id = ids.get()
if len(id) >= 9:
time.sleep(3)
print(id)
compareimage(id)
the problem is ,the textbox stop to get input after 8 char id input in textbox
I can’t input until 9 length id in my textbox
but in my console it can still print untul 9 lenght id
how can i solve this,
can anyone please help me?
i add this code to my question
def compareimage(id):
try:
path = folder + id
ClassNames = []
mylist = os.listdir(path)
for cls in mylist:
curImg = cv2.imread(f'{path}/{cls}')
image.append(curImg)
ClassNames.append(os.path.splitext(cls)[0])
encodeListKnown = finencode(image)
print(encodeListKnown)
print(ClassNames)
print(mylist)
time.sleep(3)
while (True):
ret, frames = cap.read()
frames =cv2.flip(frames,1)
gray = cv2.cvtColor(frames, cv2.COLOR_BGR2RGB)
imgS = cv2.resize(frames, (0, 0), None, 0.25, 0.25)
imgS = cv2.resize(frames, (0, 0), None, 0.25, 0.25)
imgS = cv2.cvtColor(imgS, cv2.COLOR_BGR2RGB)
facecurentframe = face_recognition.face_locations(imgS)
encodecurframe = face_recognition.face_encodings(imgS, facecurentframe)
encodelistface = []
for faceloc in zip(encodecurframe, facecurentframe):
encodeface = faceloc[0]
encodelistface.append(encodeface)
matches = face_recognition.compare_faces(encodeListKnown, encodelistface[0])
facedistance = face_recognition.face_distance(encodeListKnown, encodelistface[0])
print(encodelistface)
print(facedistance)
print(matches)
a = str(matches)
print(bool(matches))
if (bool(matches) == True):
print("True")
now = datetime.now()
stringnow = now.strftime('%y/%m/%d %H:%M:%S.%f')
f = open(foldertxt, "a")
logabsen = id + " , "+ stringnow + "n"
f.write(logabsen )
playsound(folderaudio)
encodelistface.clear()
encodeListKnown.clear()
image.clear()
ClassNames.clear()
inputid.delete(0,END)
break
else:
print("False")
encodelistface.clear()
encodeListKnown.clear()
image.clear()
ClassNames.clear()
inputid.delete(0,END)
break
except :
print("There is An Exception" , sys.exc_info()[0])
You can use after()
to schedule a timeout task whenever inputid
is updated. You need to pick a timeout period that is long enough between each update of inputid
by the barcode scanner. If inputid
is updated again before the scheduled timeout, you need to cancel the previous timeout task and rescheduled anther one.
If the timeout task is triggered, you can perform the face recognition in the timeout callback, but suggest to use thread to do it as it may be a time consuming task which will block tkinter
main loop.
Below is an example:
import tkinter as tk
import random
import threading
import time
def compareimage(id):
face.config(text='Checking ...', image=tk.PhotoImage())
face.update_idletasks()
# simulate the face recognition task
time.sleep(5)
# show the result image
face.image = tk.PhotoImage(file='result.png')
face.config(text=id, image=face.image)
ids.set('')
def text_completed(ids):
print('timed out')
id = ids.get()
if len(id) > 8:
print('id:', id)
threading.Thread(target=compareimage, args=(id,), daemon=True).start()
def text_changed(ids):
global timeout_id
if timeout_id:
# cancel previous scheduled task
root.after_cancel(timeout_id)
if len(ids.get()) > 0:
# schedule a timeout task, adjust the delay to suit your real situation
timeout_id = root.after(1000, text_completed, ids)
# simulate barcode reader input
def scan_id(n=10):
if n > 0:
inputid.insert('end', random.choice('1234567890'))
inputid.after(50, scan_id, n-1)
timeout_id = None
root = tk.Tk()
tk.Label(root, text='Employee Attandance', font='Helvetica 32 bold').pack()
ids = tk.StringVar(value='')
ids.trace('w', lambda *args: text_changed(ids))
inputid = tk.Entry(root, font='Helvetica 20 bold', textvariable=ids, width=12)
inputid.pack()
face = tk.Label(root, text='', image=tk.PhotoImage(), compound='top', width=600, height=400)
face.pack()
tk.Button(root, text='Scan ID', command=lambda: scan_id(random.randrange(9,11))).pack()
root.mainloop()
Note that the button Scan ID
is to simulate the barcode reader.
Answered by acw1668 on January 29, 2021
I refactored your script and removed all the unnecessary fluff. I also removed your wait and the compareimage
call that you did not provide. It works fine. My guess is that either the wait or the call to compareimage
were stealing focus from and/or blocking your Entry
. If you take my version of your script and add in the wait
and call, one at a time, you should be able to figure out what is blocking your Entry
.
Note: There is no reason to call pack
before place
, and I have no clue what size()
is supposed to do. ids
is already global so, all the hoops you jumped through to plug it into a lambda
were unnecessary. If something is >= 9
it is also simply > 8
import tkinter as tk
root = tk.Tk()
root.geometry('800x600+300+300')
ids = tk.StringVar(value="")
inputid = tk.Entry(root, font="Helvetica 20 bold", textvariable=ids)
inputid.place(relx=0.5, rely=0.187, width=300, height=30, anchor='sw')
def textchanged(*args):
id = ids.get()
if len(id) > 8:
print(id)
ids.trace("w", textchanged)
root.mainloop()
Answered by Michael Guidry on January 29, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP