Search code examples
python-3.xuser-interfacetkinterbarcode-scannerscanning

Check widget entry and proceed with no click nor button GUI


I am creating QR Code scanner, which slices the scanned code right after scanning it into the widget entry - in a way that no click button or keyboard press is needed to proceed in the operation. All the user has available is a barcode scanner gun.

The scanned code example input looks like this and is always structured similarly(6 substrings in 39 characters):

AAAAA-BBBBB-CCC-DDDDDD-EEEEEE-FFFFFFFFFF

I want my code to:

1) Create GUI Tkinter interface with entry for scanned code and six additional entry boxes (see picture, link below)

2) Set cursor focus in "Scanned code" entry

3) Check if the widget entry for "Scanned code" is empty

4) If false, then slice the scanned string in substrings divided by symbol '-',i.e. once it reaches '-'. Thus, I'd like to it automatically sorted into:

AAAAA

BBBBB

CCC and so on appearing in corresponding box.

So far, I have achieved to proceed with step 1) and 2) - see the picture and the code attached.

from Tkinter import *

root = Tk()
root.title('Scanner')

# create the top container
top_frame = Frame(root)
top_frame.pack( side = TOP )

scan_pcb=Label(top_frame,text='SCANNED CODE: ')
scan_pcb.grid(row=0,column=0)

pcb_entry=Entry(top_frame,background='white')
pcb_entry.grid(row=0,column=1)
pcb_entry.focus_set() 

# create the left container
left_frame = Frame(root)
left_frame.pack( side = LEFT )

A_label=Label(left_frame,text='A')
A_label.grid(row=0,column=0)
A_entry=Entry(left_frame,background='white')
A_entry.grid(row=0,column=1)

B_label=Label(left_frame,text='B')
B_label.grid(row=1,column=0)
B_entry=Entry(left_frame,background='white')
B_entry.grid(row=1,column=1)

C_label=Label(left_frame,text='C')
C_label.grid(row=2,column=0)
C_entry=Entry(left_frame,background='white')
C_entry.grid(row=2,column=1)

# create the right container
right_frame = Frame(root)
right_frame.pack( side = RIGHT )

D_label=Label(right_frame,text='D')
D_label.grid(row=0,column=2)
D_entry=Entry(right_frame,background='white')
D_entry.grid(row=0,column=3)

E_label=Label(right_frame,text='E')
E_label.grid(row=1,column=2)
E_entry=Entry(right_frame,background='white')
E_entry.grid(row=1,column=3)

E_label=Label(right_frame,text='F')
E_label.grid(row=2,column=2)
E_entry=Entry(right_frame,background='white')
E_entry.grid(row=2,column=3)

root.mainloop()

Picture of the GUI I have made so far

picture of the GUI I have made so far

However, I am struggling with step 3) and 4). I have done some research and I was thinking using

if len(entry_object.get()) from this topic somehow, maybe like:

if len(pcb_entry.get()) != 0
     #do something

The #do something part is what I am fighting with. I was also thinking maybe to make it textvariable so I could store it and work with the scanned code later on. (?)

All in all, I just cannot make it work properly and I was wondering whether there is someone willing to help me?

FYI, I am still a total novice in both python programming so huge sorry if I am duplicating the question again.

Thank you very much. Appreciate it.


Solution

  • To build a function that will check ever one second for a scan code you need to use the after() method to manage a loop that calls the function every second.

    Next it would be best to place all your entry fields inside of a list. This will let us use the index of the string split to place the data in each section of the reader.

    In the below example it will take a pasted string and split it at the -. It will then delete the string as to not cause problems later and append all the sections to the other entry fields.

    I tested with this example: # AAAA-BBBB-CCCC-DDDD-EEEE-FFFF:

    import Tkinter as tk
    
    root = tk.Tk()
    root.title('Scanner')
    entry_list = []
    
    top_frame = tk.Frame(root)
    top_frame.pack(side="top")
    tk.Label(top_frame, text='SCANNED CODE: ').grid(row=0, column=0)
    pcb_entry=tk.Entry(top_frame, background='white')
    pcb_entry.grid(row=0, column=1)
    
    left_frame = tk.Frame(root)
    left_frame.pack(side="left")
    right_frame = tk.Frame(root)
    right_frame.pack(side="right")
    tk.Label(left_frame, text='A').grid(row=0, column=0)
    tk.Label(left_frame, text='B').grid(row=1, column=0)
    tk.Label(left_frame, text='C').grid(row=2, column=0)
    tk.Label(right_frame,text='D').grid(row=0, column=2)
    tk.Label(right_frame,text='E').grid(row=1, column=2)
    tk.Label(right_frame,text='F').grid(row=2, column=2)
    
    for i in range(6):
        if i <= 2:
            entry_list.append(tk.Entry(left_frame, background='white'))
            entry_list[i].grid(row=i, column=1)
        else:
            entry_list.append(tk.Entry(right_frame, background='white'))
            entry_list[i].grid(row=i-3, column=3)
    
    def check_entry():
        x = pcb_entry.get()
        section_list = []
        if x.strip() != "":
            pcb_entry.delete(0, "end")
            section_list = x.split("-")
        for ndex, section in enumerate(section_list):
            if ndex <= 5:
                entry_list[ndex].delete(0, "end")
                entry_list[ndex].insert(0, section)
        root.after(1000, check_entry)
    
    check_entry()      
    pcb_entry.focus_set() 
    root.mainloop()
    

    Results:

    enter image description here

    Keep in mind this code is assuming you will always have 6 segments to your bar-code. If you do not always have 6 segments you will need to add in a loop that deletes all the entry fields data in the list before appending new data.