Добавление кнопки «Удалить» в графический интерфейс сканера Rfid - PullRequest
0 голосов
/ 08 июля 2019

Я работаю над умной корзиной. Я интегрировал RFID-считыватель с Raspberry Pi, который сканирует карты-метки как продукт и добавляет их в корзину для выставления счетов.

Я хочу добавить кнопку удаления функциональности в моем графическом интерфейсе. Код содержит delete() функция и кнопка, содержащая эту функцию, но проблема в том, что я могу заставить работать кнопку или модуль RFID для чтения тегов.

Чтобы кнопки были активными, я звоню root.mainloop(), что технически завершает программу, и считыватель RfID не сканирует теги после этого. Если я добавлю строку root.mainloop(), это будет иначе.

Я новичок в Python, и любая помощь будет оценена. Я приложил код для дальнейшего использования. Спасибо!

from Tkinter import *
import ttk
import sqlite3

import signal
import time
import sys
from pirc522 import RFID



root = Tk()
root.geometry("800x300")



def delete(self):
       selected_item = self.tree.selection()[0] ## get selected item
       self.tree.delete(selected_item)

class Item(object): 
    def __init__(self, unq_id, name, qty, price):
        self.unq_id = unq_id
        self.product_name = name
        self.price = price
        self.qty = qty

'''
def remove_all(self):
           x = self.cart.tree.get_children()
           print('get children values: ',x,'\n')
           if x!= '()':
               for child in x:
                   self.cart.tree.delete(child)
'''


class Cart(object):



    def __init__(self, master=None):
        self.content = dict()
        self.tree= ttk.Treeview(root, column=("column1", "column2", "column3","column4"), show='headings')
        self.tree.heading("#1", text="ITEM ID")
        self.tree.column("#1", anchor = "center", width=135)
        self.tree.heading("#2", text="ITEM NAME")
        self.tree.column("#2", anchor = "center", width=135)                 
        self.tree.heading("#3", text="QUANTITY")
        self.tree.column("#3", anchor = "center", width=135)                 
        self.tree.heading("#4", text="PRICE(Rs)")
        self.tree.column("#4", anchor = "center", width=135)
        self.tree.button_del = Button(root, text="del",command=delete(self))
        self.tree.button_del.pack()
        self.tree.pack()


        ''' '''



        ''','''



    def update(self, unq_id,product_name,price):

        if unq_id not in self.content:
            item = Item(unq_id,product_name,1,price)  
            treeRow= Item.unq_id,item.product_name,item.qty,item.price)#tuple      
            self.tree.insert("", END, values=treeRow)
        else:
            #Already exists
            item = self.content.get(unq_id)
            for index in self.tree.get_children():
                if unq_id == self.tree.item(index)['values'][0]:
                    x = index
            item.qty=item.qty+1
            treeRow=(item.unq_id,item.product_name,item.qty,item.price)
            self.tree.item(x, values = treeRow)

        self.content.update({item.unq_id: item})
        return


    def get_total(self):
        return sum([v.price * v.qty for _, v in self.content.iteritems()])

    def get_num_items(self):
        return sum([v.qty for _, v in self.content.iteritems()])
    '''
    def remove_item(self, key):
        self.content.pop(key)
    '''
    def get_item(self, key):
        return self.content.get(key)


class Application(Frame):


    def __init__(self, master=None):
        self.database = "smartShoppingCart.db"        
        Frame.__init__(self, master)
        self.v = StringVar()

        self.cart = Cart(master)
        self.pack()


        conn = sqlite3.connect(self.database)
        cur = conn.cursor()
        cur.execute("CREATE TABLE IF NOT EXISTS profile(id INTEGER PRIMARY KEY, Name TEXT, Qty INT, Price REAL, rfidTag INT)")
        #below test case ...will be removed later
        #cur.execute("INSERT INTO profile(id,Name,Qty,Price,rfidTag) VALUES (1, 'Banana', 1, 2., 230)")
        #cur.execute("INSERT INTO profile(id,Name,Qty,Price,rfidTag) VALUES (2, 'Eggs', 2, 5., 131)")
        #cur.execute("INSERT INTO profile(id,Name,Qty,Price,rfidTag) VALUES (3, 'Donut', 3, 1., 128)")
        #above test case ...will be removed later
        conn.commit()
        conn.close()
        Label(root, anchor=W, fg="green", justify=RIGHT, font=("Helvetica", 16), text="Total").pack(side = LEFT)
        Label(root, anchor=W, fg="red", justify=RIGHT, font=("Helvetica", 16), textvariable=self.v).pack(side = RIGHT)
        self.v.set("0.0")


    def insertItemToCart(self, rfidTag):
        #fetch data from database
        string ="SELECT * FROM profile WHERE rfidTag = "+str(rfidTag)
        conn = sqlite3.connect(self.database)
        cur = conn.cursor()
        cur.execute(string)
        rows = cur.fetchall()
        row = rows[0]
        conn.close()
        #update cart
        unq_id=row[4]
        name=row[1]
        price=row[3] 

        self.cart.update(unq_id, name, price)
    '''    

    '''

def end_read(signal,frame):
    global run
    print("\nCtrl+C captured, ending read.")
    run = False
    rdr.cleanup()
    sys.exit()
signal.signal(signal.SIGINT, end_read)

run = True
rdr = RFID()
app = Application(master=root)
app.master.title('Smart shopping cart')          

print("Starting")
while run:

    app.update_idletasks()
    app.update()
    rdr.wait_for_tag()
    (error, data) = rdr.request()
    if not error:
        print("\nDetected: " + format(data, "02x"))
    (error, uid) = rdr.anticoll()
    if not error:
        print("Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3]))
        time.sleep(1)
        print(uid[0])   
        app.insertItemToCart(uid[0])
        app.v.set(str(app.cart.get_total()))
    print "You have %i items in your cart for a total of $%.02f" % (app.cart.get_num_items(), app.cart.get_total())

self.tree.mainloop()

1 Ответ

0 голосов
/ 08 июля 2019

У меня нет RFid для тестирования, но я бы создал функцию без wait_for_rfid и использовал бы root.after() вместо while. Таким образом, он все равно будет работать в цикле, но не будет блокировать mainloop().

def check_rdif():

    (error, data) = rdr.request()

    if not error:
        print("\nDetected: " + format(data, "02x"))
        (error, uid) = rdr.anticoll()
        print("Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3]))
        print(uid[0])   
        app.insertItemToCart(uid[0])
        app.v.set(str(app.cart.get_total()))
        print "You have %i items in your cart for a total of $%.02f" % (app.cart.get_num_items(), app.cart.get_total())

     if run:
         # repeate after 20ms (0.2s)
         root.after(20, check_rdif)

А потом

rdr = RFID()
app = Application(master=root)

print("Starting")
check_rdif()

self.tree.mainloop()

after() не запускает его напрямую. Он отправляет его на mainloop(), который проверяет время в цикле, и запускает его через 20 мс.


Я проверил исходный код для wait_for_rfid, и он также использует цикл while, поэтому в конечном итоге я бы использовал код из этого цикла в check_rdif, но я думаю, что нет необходимости использовать wait_for_rfid

Ссылка на wait_for_rfid в исходном коде


РЕДАКТИРОВАТЬ: не проверено

from Tkinter import *
import ttk
import sqlite3

import signal
import time
import sys
from pirc522 import RFID


# --- classes ---

def delete(self):
       selected_item = self.tree.selection()[0] ## get selected item
       self.tree.delete(selected_item)


class Item(object): 

    def __init__(self, unq_id, name, qty, price):
        self.unq_id = unq_id
        self.product_name = name
        self.price = price
        self.qty = qty

class Cart(object):

    def __init__(self, master=None):
        self.content = dict()
        self.tree= ttk.Treeview(root, column=("column1", "column2", "column3","column4"), show='headings')
        self.tree.heading("#1", text="ITEM ID")
        self.tree.column("#1", anchor = "center", width=135)
        self.tree.heading("#2", text="ITEM NAME")
        self.tree.column("#2", anchor = "center", width=135)                 
        self.tree.heading("#3", text="QUANTITY")
        self.tree.column("#3", anchor = "center", width=135)                 
        self.tree.heading("#4", text="PRICE(Rs)")
        self.tree.column("#4", anchor = "center", width=135)
        self.tree.button_del = Button(root, text="del",command=delete(self))
        self.tree.button_del.pack()
        self.tree.pack()

    def update(self, unq_id,product_name,price):

        if unq_id not in self.content:
            item = Item(unq_id,product_name,1,price)  
            treeRow= Item.unq_id,item.product_name,item.qty,item.price)#tuple      
            self.tree.insert("", END, values=treeRow)
        else:
            #Already exists
            item = self.content.get(unq_id)
            for index in self.tree.get_children():
                if unq_id == self.tree.item(index)['values'][0]:
                    x = index
            item.qty=item.qty+1
            treeRow=(item.unq_id,item.product_name,item.qty,item.price)
            self.tree.item(x, values = treeRow)

        self.content.update({item.unq_id: item})
        return


    def get_total(self):
        return sum([v.price * v.qty for _, v in self.content.iteritems()])

    def get_num_items(self):
        return sum([v.qty for _, v in self.content.iteritems()])
    '''
    def remove_item(self, key):
        self.content.pop(key)
    '''
    def get_item(self, key):
        return self.content.get(key)


class Application(Frame):

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()

        self.database = "smartShoppingCart.db"        
        self.v = StringVar()

        self.cart = Cart(master)

        conn = sqlite3.connect(self.database)
        cur = conn.cursor()
        cur.execute("CREATE TABLE IF NOT EXISTS profile(id INTEGER PRIMARY KEY, Name TEXT, Qty INT, Price REAL, rfidTag INT)")
        #below test case ...will be removed later
        #cur.execute("INSERT INTO profile(id,Name,Qty,Price,rfidTag) VALUES (1, 'Banana', 1, 2., 230)")
        #cur.execute("INSERT INTO profile(id,Name,Qty,Price,rfidTag) VALUES (2, 'Eggs', 2, 5., 131)")
        #cur.execute("INSERT INTO profile(id,Name,Qty,Price,rfidTag) VALUES (3, 'Donut', 3, 1., 128)")
        #above test case ...will be removed later
        conn.commit()
        conn.close()
        Label(root, anchor=W, fg="green", justify=RIGHT, font=("Helvetica", 16), text="Total").pack(side = LEFT)
        Label(root, anchor=W, fg="red", justify=RIGHT, font=("Helvetica", 16), textvariable=self.v).pack(side = RIGHT)
        self.v.set("0.0")


    def insertItemToCart(self, rfidTag):
        #fetch data from database
        string ="SELECT * FROM profile WHERE rfidTag = "+str(rfidTag)
        conn = sqlite3.connect(self.database)
        cur = conn.cursor()
        cur.execute(string)
        rows = cur.fetchall()
        row = rows[0]
        conn.close()
        #update cart
        unq_id=row[4]
        name=row[1]
        price=row[3] 

        self.cart.update(unq_id, name, price)

# --- functions ---

def end_read(signal,frame):
    global run
    print("\nCtrl+C captured, ending read.")
    run = False
    rdr.cleanup()
    sys.exit()

def check_rdif():

    (error, data) = rdr.request()

    if not error:
        print("\nDetected: " + format(data, "02x"))
        (error, uid) = rdr.anticoll()
        print("Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3]))
        print(uid[0])   
        app.insertItemToCart(uid[0])
        app.v.set(str(app.cart.get_total()))
        print "You have %i items in your cart for a total of $%.02f" % (app.cart.get_num_items(), app.cart.get_total())

     if run:
         # repeate after 20ms (0.2s)
         root.after(20, check_rdif)

# --- main ---

signal.signal(signal.SIGINT, end_read)
run = True

root = Tk()
root.geometry("800x300")
root.title('Smart shopping cart')          

rdr = RFID()
app = Application(master=root)

print("Starting")
check_rdif()

self.tree.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...