如何在 Tkinter 中实现数据库在帧之间的切换?

How to implement a database in Tkinter switching between frames?

我的工作基于 Switch between two frames in tkinter,它仍然是一个正在进行的项目,但我在使用数据库时经常遇到问题。

这是我的代码:

import tkinter as tk

import sqlite3

import threading

class SampleApp(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

        self.resizable(0,0)

        self.title("Findex")

        w, h = self.winfo_screenwidth(), self.winfo_screenheight()

        self.overrideredirect(1)

        self.geometry("%dx%d+0+0" % (w, h))

        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 (Inicio, Registro, RegistroError, Consulta):

            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("Inicio")

    def show_frame(self, page_name):

        frame = self.frames[page_name]

        frame.tkraise()

    def get_page(self, page_class):

        return self.frames[page_class]

class Inicio(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)

        self.controller = controller

        labelInicio = tk.Label(self, text = "Bienvendido a Findex")

        labelInicio.pack()

        botonIncio = tk.Button(self, text = "Comenzar", 
            command = lambda: controller.show_frame("Registro"))

        botonIncio.pack()

class Registro(tk.Frame):

     def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)

        self.controller = controller

        def Usuario():

            if entryNombre.get() == "":

                labelError.config(text = "No introdujo ningún nombre")

            else:

                labelError.config(text = "")

                labelNombre = tk.Label(self,
                 text = "Ha escrito " + entryNombre.get() +
                  " ¿es correcto?")

                labelNombre.pack()

                def Paso():

                    controller.show_frame("Consulta")

                def Tiempo():

                    timer = threading.Timer(3.0, Paso)

                    timer.start()

                    labelAcceso = tk.Label(self,
                     text = "Adelante, " + entryNombre.get())

                    labelAcceso.pack()

                botonSi = tk.Button(self, text = "Sí",
                 command = Tiempo)

                botonSi.pack()

                botonNo = tk.Button(self, text = "No", 
                    command = lambda: controller.show_frame("RegistroError"))

                botonNo.pack()

        labelInstruction = tk.Label(self,
         text = "Para continuar introduzca su nombre")

        labelInstruction.pack()

        entryNombre = tk.Entry(self)

        entryNombre.pack()

        botonConfirmar = tk.Button(self, text = "Confirmar",
         command = Usuario)

        botonConfirmar.pack()

        labelError = tk.Label(self)

        labelError.pack()

class RegistroError(tk.Frame):

     def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)

        self.controller = controller

        def Usuario():

            if entryNombre.get() == "":

                labelError.config(text = "No introdujo ningún nombre")

            else:

                labelError.config(text = "")

                labelNombre = tk.Label(self,
                 text = "Ha escrito " + entryNombre.get() +
                  " ¿es correcto?")

                labelNombre.pack()

                def Paso():

                    controller.show_frame("Consulta")

                def Tiempo():

                    timer = threading.Timer(2.0, Paso)

                    timer.start()

                    labelAcceso = tk.Label(self,
                     text = "Adelante, " + entryNombre.get())

                    labelAcceso.pack()

                botonSi = tk.Button(self, text = "Sí",
                 command = Tiempo)

                botonSi.pack()

                def Error():

                    labelNombre.config(text = "")

                    labelInstruction.config(text = "")

                    botonSi.config(state = "disabled")

                    botonNo.config(state = "disabled")

                    entryNombre.config(state = "disabled")

                    botonConfirmar.config(state = "disabled")

                    labelFin = tk.Label(self, 
                        text = "Se han agotado las oportunidades. Inténtelo de nuevo")

                    labelFin.pack()

                    def Salir():

                        quit()

                    botonSalir = tk.Button(self, text = "Aceptar y Salir", 
                        command = Salir)

                    botonSalir.pack()

                botonNo = tk.Button(self, text = "No" , command = Error)

                botonNo.pack()

        labelInstruction = tk.Label(self,
         text = "Para continuar introduzca su nombre")

        labelInstruction.pack()

        entryNombre = tk.Entry(self)

        entryNombre.pack()

        botonConfirmar = tk.Button(self, text = "Confirmar",
         command = Usuario)

        botonConfirmar.pack()

        labelError = tk.Label(self)

        labelError.pack()

class Consulta(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)

        self.controller = controller

        labelConsulta = tk.Label(self, 
            text = "Ingrese el nombre de un producto, marca o tienda",
             padx = 30, pady = 15)

        labelConsulta.pack()

        entryConsulta = tk.Entry(self)

        entryConsulta.pack()

        def Call():

            miConexion = sqlite3.connect("Findex")

            miCursor = miConexion.cursor()

            query = entryConsulta.get()

            miCursor.execute("SELECT * FROM PRODUCTOS WHERE NOMBRE = ? OR MARCA = ? OR ESTABLECIMIENTO = ?", query)

            table = miCursor.fetchall()

            textConsulta.insert(1.0, table)

            miConexion.commit()

        botonConsulta = tk.Button(self, text = "Buscar", command = Call)

        botonConsulta.pack()

        textConsulta = tk.Text(self, bd = 2)

        textConsulta.pack()

if __name__ == "__main__":

    app = SampleApp()

    app.mainloop()

这里是我创建数据库的地方:

    import sqlite3

miConexion = sqlite3.connect("Findex")

miCursor = miConexion.cursor()

miCursor.execute("""

    CREATE TABLE IF NOT EXISTS 'PRODUCTOS' (

    ID INTEGER PRIMARY KEY AUTOINCREMENT,
    NOMBRE VARCHAR(50),
    MARCA VARCHAR(50),
    PESO INTEGER,
    UNIDAD VARCHAR(20),
    PRECIO INTEGER,
    CATEGORIA VARCHAR(50),
    ESTABLECIMIENTO VARCHAR(50))

    """)

datos = [

    ("Sirope", "Suli", 700, "mililitros", 300, "Bebidas", "Palí"),
    ("Azúcar", "Doña María", 2, "kilogramos", 1225, "Granos",  "Palí"),
    ("Arroz", "Indiana", 1800, "gramos", 1495, "Granos", "Palí"),
    ("Café", "Rey", 500, "gramos", 1525, "Bebidas", "Palí"),
    ("Frijoles", "Indiana", 900, "gramos", 1175, "Granos", "Palí"),
    ("Sal", "Sal Sol", 500, "gramos", 225, "Granos", "Palí"),
    ("Aceite", "Clover", 1.5, "litros", 675, "Aceite/Margarina/Mantequilla", "Palí"),
    ("Huevos", "Don Cristóbal", 500, "gramos", 1975, "Huevos", "Palí"),
    ("Cereal", "Jack's", 250, "gramos", 2100, "Cereales", "Palí"),
    ("Mantequilla", "Dos Pinos", 500, "gramos", 675, "Aceite/Margarina/Mantequilla", "Palí"),
    ("Leche", "Dos Pinos", 1, "litros", 504, "Lácteos", "Palí"),
    ("Fideos", "Roma", 200, "gramos", 485, "Pastas", "Palí"),
    ("Jabón", "Fort 3", 1, "kilogramos", 550, "Limpieza", "Palí"),
    ("Desinfectante", "Floral", 750, "mililitros", 550, "Limpieza", "Palí"),
    ("Crema dental", "Oral B", 53, "mililitros", 900, "Cuidado personal", "Palí"),
    ("Jabón de baño", "Protex", 110, "gramos", 505, "Cuidado personal", "Palí"),
    ("Galletas", "Pozuelo", 31.5, "gramos", 1400, "Snacks", "Palí"),
    ("Papel higiénico", "Nevax", 1000, "hojas", 2450, "Cuidado personal", "Palí"),
    ("Toallas", "Nevax", 100, "hojas", 1300, "Limpieza", "Palí"),
    ("Refresco", "Lio-Té", 100, "gramos", 240, "Bebidas", "Palí"),
    ("Leche", "Delactomy", 1000, "mililitros", 2795, "Lácteos", "Perimercados"),
    ("Jamón cocido", "Cinta Azul", 250, "gramos", 2285, "Embutidos", "Perimercados"),
    ("Salsa inglesa", "Banquete", 700, "gramos", 1950, "Salsas", "Perimercados"),
    ("Aceite", "Capullo", 900, "mililitros", 925, "Aceite/Margarina/Mantequilla", "Perimercados"),
    ("Detergente", "Xedex", 5000, "gramos", 7750, "Limpieza", "Perimercados"),
    ("Lavaplatos", "Axion", 850, "gramos", 1610, "Limpieza", "Perimercados"),
    ("Arroz", "Imperio", 1, "kilogramos", 1180, "Granos", "Perimercados"),
    ("Pasta tipo cabello ángel", "Roma", 250, "gramos", 645, "Pastas", "Perimercados"),
    ("Pan blanco", "Bimbo", 450, "gramos", 1285, "Panes", "Perimercados"),
    ("Frijoles molidos", "Ducal", 400, "gramos", 910, "Enlatados", "Perimercados"),
    ("Crema dental", "Colgate", 75, "mililitros", 1390, "Cuidado personal", "Perimercados"),
    ("Protectores diarios", "Saba", 60, "unidades", 1495, "Cuidado personal", "Perimercados"),
    ("Café", "1820", 340, "gramos", 2810, "Bebidas", "Perimercados"),
    ("Avena", "Quaker", 300, "gramos", 805, "Cereales", "Perimercados"),
    ("Yogurt", "Yoplait", 750, "gramos", 1610, "Lácteos", "Perimercados"),
    ("Tomate", "-", 1, "kilogramos", 1050, "Frutas", "Perimercados"),
    ("Uvas mixtas", "-", 500, "gramos", 2600, "Frutas", "Perimercados"),
    ("Muslo de pollo", "-", 1, "kilogramos", 2300, "Carnes", "Perimercados"),
    ("Chorizo", "-", 1, "kilogramos", 3020, "Carnes", "Perimercados"),
    ("Queso", "Zarcero", 1, "kilogramos", 4200, "Lácteos", "Perimercados"),
    ("Aceite", "Capullo", 900, "mililitros", 880, "Aceite/Margarina/Mantequilla", "Megasuper"),
    ("Café", "Rey Selecto", 500, "gramos", 1995, "Bebidas", "Megasuper"),
    ("Margarina", "Numar", 452, "gramos", 1045, "Aceite/Margarina/Mantequilla", "Megasuper"),
    ("Yogurt", "Coronado", 1000, "mililitros", 1675, "Lácteos", "Megasuper"),
    ("Galleta soda", "Gama", 192, "gramos", 470, "Snacks", "Megasuper"),
    ("Molida premium de res", "-", 1, "kilogramos", 5540, "Carnes", "Megasuper"),
    ("Queso Turrialba", "Dos Pinos", 1, "kilogramos", 4270, "Lácteos", "Megasuper"),
    ("Chile dulce", "-", 1, "unidades", 325, "Verduras", "Megasuper"),
    ("Sandía", "-", 1, "kilogramos", 595, "Frutas", "Megasuper"),
    ("Huevos", "-", 1, "kilogramos", 1650, "Huevos", "Megasuper"),
    ("Hongos rebanados", "Del Monte", 184, "gramos", 530, "Enlatados", "Megasuper"),
    ("Frijoles rojos", "Luisiana", 900, "gramos", 1095, "Granos", "Megasuper"),
    ("Papel higiénico", "Higienol", 4, "unidades", 1550, "Limpieza", "Megasuper"),
    ("Detergente en polvo", "Rinso", 5000, "gramos", 1650, "Limpieza", "Megasuper"),
    ("Alimento para perro", "Dog Chow", 4000, "gramos", 10640, "Mascotas", "Megasuper"),
    ("Chuleta de cerdo", "-", 1, "kilogramos", 3690, "Carnes", "Megasuper"),
    ("Cerveza", "Imperial", 350, "mililitros", 780, "Bebidas alcohólicas", "Megasuper"),
    ("Vino", "Clos", 750, "mililitros", 3320, "Bebidas alcohólicas", "Megasuper"),
    ("Posta de cerdo", "-", 1, "kilogramos", 3490, "Carnes", "Megasuper"),
    ("Toallas sanitarias", "Kotex", 12, "unidades", 1645, "Ciudades personal", "Megasuper"),
    ("Crema dental", "Colgate", 75, "mililitros", 1510, "Cuidado personal", "Freshmarket"),
    ("Frito Lay", "Tostitos", 283, "gramos", 2620, "Snacks", "Freshmarket"),
    ("Vino", "San Telmo", 750, "mililitros", 7915, "Bebidas alcohólicas", "Freshmarket"),
    ("Helado Trirts", "Dos Pinos", 540, "gramos", 2950, "Lácteos", "Freshmarket"),
    ("Repollo verde", "-", 1, "unidades", 695, "Verduras", "Freshmarket"),
    ("Néctar mixto fruta", "Dos Pinos", 1, "litros", 960, "Bebidas", "Freshmarket"),
    ("Pan baguette", "AMMM", 300, "gramos", 1000, "Panadería", "Freshmarket"),
    ("Sandía", "-", 1, "kilogramos", 850, "Frutas", "Freshmarket"),
    ("Tomate", "-", 1, "kilogramos", 1250, "Frutas", "Freshmarket"),
    ("Plátono verde", "-", 1, "unidades", 395, "Frutas", "Freshmarket"),
    ("Papa", "-", 1, "kilogramos", 1295, "Verduras", "Freshmarket"),
    ("Manga", "-", 1, "kilogramos", 1650, "Frutas", "Freshmarket"),
    ("Ron", "Flor de Caña", 750, "mililiros", 7000, "Bebidas alcohólicas", "Freshmarket"),
    ("Papas tostadas", "Lays", 184, "gramos", 1800, "Snacks", "Freshmarket"),
    ("Jugo de naranja", "Dos Pinos", 1.8, "litros", 2930, "Bebidas", "Freshmarket"),
    ("Sundae", "Dos Pinos", 110, "gramos", 1620, "Lácteos", "Freshmarket"),
    ("Bebida energética", "Gatorade", 600, "mililitros", 1460, "Bebidas", "Freshmarket"),
    ("Deligurt", "Dos Pinos", 200, "mililitros", 850, "Lácteos", "Freshmarket"),
    ("Gaseosa", "Coca Cola", 2, "litros", 2285, "Bebidas", "Freshmarket"),
    ("Papas tostadas", "Pringles", 125, "gramos", 2300, "Snacks", "Freshmarket"),
    ("Toalla nocturna", "Saba", 40, "unidades", 5575, "Cuidado personal", "AutoMercado"),
    ("Acondicionador para cabello", "Alea", 500, "mililitros", 4215, "Cuidado personal", "AutoMercado"),
    ("Shampoo con keratina", "Suave", 373, "mililitros", 4000, "Cuidado personal", "AutoMercado"),
    ("Atún en trozos", "Pronto", 640, "gramos", 7320, "Enlatados", "AutoMercado"),
    ("Café", "Rey", 400, "gramos", 3500, "Bebidas", "AutoMercado"),
    ("Frijoles molidos", "Ducal", 400, "gramos", 865, "Enlatados", "AutoMercado"),
    ("Mayonesa con aceite de oliva", "Alolivo", 400, "gramos", 1595, "Salsas", "AutoMercado"),
    ("Cereal integral", "Nestle", 450, "gramos", 2700, "Cereales", "AutoMercado"),
    ("Vino tinto", "Broquel", 750, "mililitros", 10785, "Bebidas alcohólicas", "AutoMercado"),
    ("Queso mozzarella", "Crystal Farms", 227, "gramos", 3250, "Lácteos", "AutoMercado"),
    ("Jamón de pavo", "Cinta Azul", 1, "kilogramos", 9925, "Embutidos", "AutoMercado"),
    ("Bistec de lomo", "AutoMercado", 1, "kilogramos", 14170, "Carnes", "AutoMercado"),
    ("Chicharrones ahumados", "Jack's", 75, "gramos", 1400, "Carnes", "AutoMercado"),
    ("Maní con miel", "The Carolina Nut Co", 340, "gramos", 3100, "Snacks", "AutoMercado"),
    ("Limón ácido", "-", 15, "unidades", 3800, "Frutas", "AutoMercado"),
    ("Filet de pechuga", "AutoMercado", 1, "kilogramos", 7875, "Carnes", "AutoMercado"),
    ("Cerveza amarga", "Warsteiner", 500, "mililitros", 1395, "Bebidas alcohólicas", "AutoMercado"),
    ("Crema croporal", "Bilka", 180, "mililitros", 10265, "Cuidado Personal", "AutoMercado"),
    ("Tinte para cabello", "Koleston", 1, "unidades", 5915, "Cuidado Personal", "AutoMercado"),
    ("Toallitas desmaquillantes", "Asepxia", 25, "unidades", 5445, "Cuidado Personal", "AutoMercado")

    ]

miCursor.executemany("INSERT INTO PRODUCTOS VALUES (NULL, ?, ?, ?, ?, ?, ?, ?)", datos)

miConexion.commit()

miConexion.close()

我希望输入产品的名称、标记或商店,并在文本字段中插入与条目匹配的所有产品信息,但它给了我 'OperationalError' 或 'sqlite3.ProgrammingError' .

我觉得问题出在这里

query = entryConsulta.get()
miCursor.execute("SELECT * FROM PRODUCTOS WHERE NOMBRE = ? OR MARCA = ? OR ESTABLECIMIENTO = ?", query)

你的声明接受了 3 个参数,但你只传递了一个

试试看

query = entryConsulta.get()
args = (query,query,query)
miCursor.execute("SELECT * FROM PRODUCTOS WHERE NOMBRE = ? OR MARCA = ? OR ESTABLECIMIENTO = ?", args)

无论如何我认为你必须在更多模块之间解耦你的代码,如果你对这种类型的程序感兴趣我会建议你这是我的 github

的教学工作

https://github.com/1966bc/Tkinterlite

快跑;)