I am new to threading so I'm sorry for any mistakes there are. I am creating a GUI where the user will input their pin using the 4x4 membrane keypad with the raspberry pi and that input will be compared with the pin they have in the database. I currently have it so that when a button is pressed, the code for the keypad will run in a thread. The issue I'm having is when the pin is correct or too many attempts are made, the thread with the keypad code is still running. I've tried different ways that I've found online, to try and stop the thread, as seen in the code.
Is there a way to stop the thread, or will I have to try a different approach if I want to stop the code when the user input is either wrong/correct? I would appreciate the help.
import threading
import tkinter as tk
from tkinter import font as tkfont
from pad4pi import rpi_gpio
import time
import sys
import RPi.GPIO as GPIO
KEYPAD1 = [
["1","2","3","A"],
["4","5","6","B"],
["7","8","9","C"],
["*","0","#","D"]
]
#passcode = "7A7B"
passcode = ""
inp = ""
a = 0
GPIO.setwarnings(False)
ROW_PINS = [5, 6, 13, 19] # BCM numbering;
COL_PINS = [12, 16, 20, 21] # BCM numbering;
factory = rpi_gpio.KeypadFactory()
keypad = factory.create_keypad(keypad=KEYPAD1, row_pins=ROW_PINS, col_pins=COL_PINS)
def PAD(self, val, stop):
global passcode
passcode = val
def pressKey(key):
global inp # where the key will be added to
global a # attempts user has made
if (key == "*"):
print("Input reset")
inp = ""
a += 1
elif (key == "#"):
if len(inp) > len(passcode):
print("Input longer than passcode, resetting")
inp = ""
a += 1
elif (inp == passcode):
self.label1.destroy()
inp = ""
a = 0
self.controller.show_frame("Access")
print("Unlocking door")
time.sleep(5)
print("Door locked")
self.controller.show_frame("StartPage")
stop()
sys.tracebacklimit=1
raise ValueError()
else:
print("Passcode incorrect")
inp = ""
a+=1
else:
inp = inp + key
time.sleep(0.1)
# after 4 attempts, stops
if a == 4:
self.controller.show_frame("Denied")
print("Too many tries, exitting")
self.label1.destroy()
a = 0
inp = ""
time.sleep(5)
self.controller.show_frame("StartPage")
stop()
sys.tracebacklimit=1
raise ValueError()
# pressKey will be called each time a keypad button is pressed
keypad.registerKeyPressHandler(pressKey)
while True:
try:
time.sleep(0.1)
if stop():
break
except:
keypad.cleanup()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne, Denied, Access):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Go to Page One",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Keypad",
command=lambda: self.create())
button1.pack()
button2.pack()
def create(self):
self.label1 = tk.Label(self, text = "Please input passcode via keypad")
self.label1.pack()
self.after(200, self.key_pad())
def key_pad(self):
stop_thread = False
value = "7A7B"
t = threading.Thread(target=PAD, args=(self,value, lambda: stop_thread))
t.daemon = True
t.start()
stop_thread = True
t.join()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
class Access(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = "green")
label = tk.Label(self, text = "Granted", font = controller.title_font)
label.pack()
button = tk.Button(self, text = "Home", command = lambda: self.controller.show_frame("StartPage"))
button.pack()
class Denied(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = "red")
label = tk.Label(self, text = "denied", font = controller.title_font)
label.pack()
button = tk.Button(self, text = "Home", command = lambda: self.controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()