Search code examples
eventstkintertextboxbind

Reading Keystrokes and Placing into Textbox


I am a teacher that is writing a program to read an 8-digit ID barcode for students who are late to school. I am an experienced programmer, but new to Python and very new to Tkinter (about 36 hours experience) I have made heavy use of this site so far, but I have been unable to find the answer to this question:

How can I read exactly 8 digits, and display those 8 digits in a textbox immediately. I can do 7, but can't seem to get it to 8. Sometimes, I will get nothing in the text box. I have used Entry, bind , and everything works OK, except I can't seem to get the keys read in the bind event to place the keys in the textbox consistently that were inputted. The ID seems to be always correct when I PRINT it, but it is not correct in the textbox. I seem unable to be allowed to show the tkinter screen, so it shows only 7 digits or nothing in the text box upon completion.

Here is a snippet of my code, that deals with the GUI

from tkinter import *
from collections import Counter
import time
i=0
class studentNumGUI():
    def __init__(self, master):
        master.title("Student ID Reader")
        self.idScanned = StringVar()
        localTime = time.asctime(time.localtime(time.time()))
        self.lblTime = Label(master, text=localTime)
        self.lblTime.pack()
        self.lbl = Label(master, text="Enter Student ID:")
        self.lbl.pack()
        self.idScanned.set("")
        self.idScan = Entry(master,textvariable=self.idScanned,width=12)
        self.idScan.pack()
        self.frame=Frame(width=400,height=400)
        self.frame.pack()
        self.frame.focus()
        self.frame.bind('<Key>',self.key)

    def key(self,event):
        global i
        self.frame.focus()
        self.idScan.insert(END,event.char)
        print(repr(event.char)," was pressed") #just to make sure that my keystrokes are accepted
        if (i < 7):
            i += 1
        else:
            #put my other python function calls here once I fix my problem
            self.frame.after(2000)
            #self.idScan.delete(0,END) #Then go blank for the next ID to be read
            i=0

root = Tk()
nameGUI = studentNumGUI(root)
root.mainloop()

enter image description here


Solution

  • You are doing some unusual things in order to place text inside the Entry field based on keypresses. I've changed your code so that it sets the focus on the Entry widget and will check the contents of the Entry field each time a key is pressed (while the Entry has focus). I'm then getting the contents of the Entry field and checking if the length is less than 8. If it is 8 (or greater) it will clear the box. How does this work for you? I've left in the commented out code

    from tkinter import *
    from collections import Counter
    import time
    
    class studentNumGUI():
        def __init__(self, master):
            master.title("Student ID Reader")
            self.idScanned = StringVar()
            localTime = time.asctime(time.localtime(time.time()))
            self.lblTime = Label(master, text=localTime)
            self.lblTime.pack()
            self.lbl = Label(master, text="Enter Student ID:")
            self.lbl.pack()
            self.idScanned.set("")
            self.idScan = Entry(master,textvariable=self.idScanned,width=12)
            self.idScan.pack()
            self.idScan.focus_set()
            self.frame=Frame(width=400,height=400)
            self.frame.pack()
            #self.frame.focus()
            #self.frame.bind('<Key>',self.key)
            self.idScan.bind('<Key>',self.key)
    
        def key(self,event):
            #self.frame.focus()
            #self.idScan.insert(END,event.char)
            print(repr(event.char)," was pressed") #just to make sure that my keystrokes are accepted
            len(self.idScanned.get())
            if (len(self.idScanned.get())<8):
                pass
            else:
                #put my other python function calls here once I fix my problem
                self.idScan.delete(0,END) #Then go blank for the next ID to be read
                #self.frame.after(2000)
    
    
    root = Tk()
    nameGUI = studentNumGUI(root)
    root.mainloop()